canal mysql select權限粒度

今天產品問了一個問題,問懵了

產品:canal在開通mysql權限時需要哪些權限

我:SELECT, REPLICATION SLAVE, REPLICATION CLIENT

產品:那SELECT權限要開通到表級還是庫級(我們使用canal同步數據時最終選擇到表)

我:en…..  晚會給你答案吧^-^.

於是乎今天就測試一下,不測不知道,一測怎加不加select權限都能正常同步binlog

場景一

本地有個mysql,直接在本地測試,刪除庫的select權限,也能正常同步binlog,於是乎就不淡定了,在網上查也沒有個所以然

 

場景二

於是啟動本地基於mha搭建的mysql高可用集群,再來使用canal同步主庫binlog,將所要同步庫的select權限刪除,發現報錯:

16:07:42.791 [WARN ] [destination = example7 , address = s129/192.168.3.129:3306 , EventParser] MysqlEventParser:463 | ERROR ## parse this event has an error , last position : [EntryPosition[included=false,journalName=mysql-bin.000009,position=4667,serverId=1,gtid=,timestamp=1615016220000]]
com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed.
Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: com.google.common.util.concurrent.UncheckedExecutionException: com.alibaba.otter.canal.parse.exception.CanalParseException: fetch failed by table meta:`canal`.`test_canal_2_hive`
Caused by: com.google.common.util.concurrent.UncheckedExecutionException: com.alibaba.otter.canal.parse.exception.CanalParseException: fetch failed by table meta:`canal`.`test_canal_2_hive`
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2203) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache.get(LocalCache.java:3937) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4830) ~[guava-18.0.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.TableMetaCache.getTableMeta(TableMetaCache.java:195) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.getTableMeta(LogEventConvert.java:950) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEventForTableMeta(LogEventConvert.java:479) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEvent(LogEventConvert.java:500) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEvent(LogEventConvert.java:491) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parse(LogEventConvert.java:125) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parse(LogEventConvert.java:69) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.AbstractEventParser.parseAndProfilingIfNecessary(AbstractEventParser.java:417) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3$1.sink(AbstractEventParser.java:217) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.dump(MysqlConnection.java:178) [canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3.run(AbstractEventParser.java:279) [canal.parse-1.1.4.jar:na]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: fetch failed by table meta:`canal`.`test_canal_2_hive`
Caused by: java.io.IOException: ErrorPacket [errorNumber=1142, fieldCount=-1, message=SELECT command denied to user 'canal_repl_user'@'192.168.3.1' for table 'test_canal_2_hive', sqlState=42000, sqlStateMarker=#]
 with command: desc `canal`.`test_canal_2_hive`
    at com.alibaba.otter.canal.parse.driver.mysql.MysqlQueryExecutor.query(MysqlQueryExecutor.java:61) ~[canal.parse.driver-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.query(MysqlConnection.java:106) [canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.TableMetaCache.getTableMetaByDB(TableMetaCache.java:92) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.TableMetaCache.access$000(TableMetaCache.java:32) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.TableMetaCache$1.load(TableMetaCache.java:63) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.TableMetaCache$1.load(TableMetaCache.java:53) ~[canal.parse-1.1.4.jar:na]
    at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2319) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2282) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2197) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache.get(LocalCache.java:3937) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824) ~[guava-18.0.jar:na]
    at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4830) ~[guava-18.0.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.TableMetaCache.getTableMeta(TableMetaCache.java:195) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.getTableMeta(LogEventConvert.java:950) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEventForTableMeta(LogEventConvert.java:479) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEvent(LogEventConvert.java:500) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEvent(LogEventConvert.java:491) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parse(LogEventConvert.java:125) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parse(LogEventConvert.java:69) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.AbstractEventParser.parseAndProfilingIfNecessary(AbstractEventParser.java:417) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3$1.sink(AbstractEventParser.java:217) ~[canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.dump(MysqlConnection.java:178) [canal.parse-1.1.4.jar:na]
    at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3.run(AbstractEventParser.java:279) [canal.parse-1.1.4.jar:na]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
16:07:42.792 [ERROR] [destination = example7 , address = s129/192.168.3.129:3306 , EventParser] MysqlEventParser:301 | dump address s129/192.168.3.129:3306 has an error, retrying. caused by 
com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed.
Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed.

報錯標紅的說明了,表需要select權限,於是查到對應的源碼:

 

 說明查詢表元數據時show create table tableName和desc tableName都需要select權限,於是給對應表賦予select權限,同步正常

說明只要賦予表即select權限就可以了,那為什麼本地不授權select也可以呢?

查了網上說和master_info_repository參數有關,兩個環境確實不一樣,本地master_info_repository=TABLE,mha中master_info_repository=FILE,但不知具體原因

 

使用命令:

#授權
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT, SHOW VIEW ON *.* TO `canal`@`%`
FLUSH PRIVILEGES;
#查詢權限
SHOW GRANTS FOR 'canal'@'%';
#刪除權限
REVOKE SELECT ON *.* FROM 'canal'@'%';
FLUSH PRIVILEGES;