mysql复制用户权限不足导致中断,根本原因是权限变更未同步:主从默认不复制mysql库,5.7及以前grant不写binlog,8.0+需log_bin=on且replicate_ignore_db不含mysql;修复须确保binlog开启、禁用忽略配置、用create user+grant而非直写mysql.user表。

MySQL账号必须同时有 SELECT + REPLICATION SLAVE + REPLICATION CLIENT
只给 REPLICATION SLAVE 是最常见的权限错误。Canal 或 DataX 启动时会卡在初始化阶段,报错类似 Access denied; you need (at least one of) the SUPER, REPLICATION CLIENT privilege(s),其实就缺 REPLICATION CLIENT —— 它用于执行 SHOW MASTER STATUS 和 SHOW BINLOG EVENTS,获取当前 binlog 文件名和起始位置。
SELECT 权限也不能省:Canal 需要查 information_schema 获取表结构(比如字段类型、主键),DataX 的 reader 插件在构建增量查询语句时也依赖它;没这个权限,连表都列不出来。
- 不要用
GRANT ALL PRIVILEGES:Canal/DataX 不需要写权限,也不该有 - 生产环境避免用
'canal'@'%',换成具体 IP,如'canal'@'10.20.30.40' - 阿里云 RDS for MySQL 默认已开 binlog 且账号自带
REPLICATION CLIENT和REPLICATION SLAVE,但SELECT仍需手动加
binlog-format 必须是 ROW,不能是 STATEMENT 或 MIXED
Canal 和 DataX 的 MySQL reader 增量模式都依赖 binlog 中的完整行变更数据。只有 binlog-format=ROW 才能拿到 UPDATE 前后字段值(例如 name 从“张三”变“李四”);STATEMENT 只记 SQL 语句,MIXED 切换逻辑不可控,都会导致解析失败或丢变更。
验证命令:SHOW VARIABLES LIKE 'binlog_format';,结果必须是 ROW。如果改了 /etc/my.cnf 却没生效,大概率是没重启 MySQL 服务:
- Ubuntu/Debian:
sudo systemctl restart mysql - CentOS/RHEL:
sudo systemctl restart mysqld
server_id 和 slaveId 不能为 0,且不能冲突
MySQL 的 server_id 是复制身份标识,Canal 的 canal.instance.mysql.slaveId 是它在 binlog 流中的“虚拟从库 ID”。两者都必须是非零整数,且在整个 MySQL 集群中唯一——否则 MySQL 主库可能拒绝 dump 请求,Canal 报 Could not find first log file name in binary log index file。
常见踩坑点:
-
server_id=1是安全起点,但如果你的集群已有从库用了 1,就得换,比如 101、201 -
canal.instance.mysql.slaveId不能和任何真实从库的server_id相同,建议设为大于 1000 的值(如 1001),避开常规部署范围 - 别把
slaveId设成 0:Canal 会自动 fallback 到随机数,但行为不可控,首次启动极易跳过日志
canal.instance.master.position 初始偏移量填错会导致丢数据
Canal 第一次启动时,靠 canal.instance.master.journal.name 和 canal.instance.master.position 定位 binlog 起始点。填错不是报错退出,而是静默跳过部分日志——你根本不知道丢了哪几条。
正确做法是:先用 MySQL 命令查当前最新 binlog 位置:
mysql> SHOW MASTER STATUS; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000005 | 12345678 | | | | +------------------+----------+--------------+------------------+-------------------+
然后把 File 填进 canal.instance.master.journal.name,Position 填进 canal.instance.master.position。如果想从头同步,得用 mysql-bin.000001 开头的文件,但注意:该文件可能已被 expire_logs_days 清理掉。
最易被忽略的一点:这个初始位置是“一次性快照”,后续 Canal 自动维护 offset。一旦启动成功,就别再手动改它——除非你明确要重置同步点并接受重复或丢失。











