mysql系统库mysql不参与主从复制,因内部结构变更可能引发从库崩溃;必须手动同步user、db等权限表,否则导致权限漂移、连接失败或越权访问。

MySQL 分布式集群中无法靠 GRANT 语句自动同步权限 —— 系统库 mysql 不参与主从复制,也不被大多数 CDC 工具默认捕获。 必须显式同步 mysql.user、mysql.db、mysql.tables_priv 等表,否则节点间权限会漂移,导致应用连接失败或越权访问。
为什么 mysql 库不随主从复制自动同步
MySQL 原生复制默认过滤掉 mysql 系统库(即使未显式配置 replicate-ignore-db=mysql),因为其内部表结构变更可能引发从库崩溃。5.7+ 版本虽支持 replicate-rewrite-db 或 --replicate-do-table=mysql.user,但风险极高:任意节点执行 CREATE USER 后,其他节点若未同步该行,FLUSH PRIVILEGES 也无法补救。
常见错误现象:
- 新用户在主库创建成功,但从库登录报
Access denied for user - 主库已
DROP USER,但从库仍能用旧账号登录 -
SHOW GRANTS FOR 'u'@'%'在各节点返回结果不一致
用 mysqldump + mysql 手动同步系统库的实操要点
这是最可控、最低风险的方式,适合中小规模集群(≤20 节点)和定期维护场景。
操作前确认:
- 所有节点 MySQL 版本一致(尤其注意 5.7 和 8.0 的
mysql.user字段差异,如plugin、account_locked) - 主库已执行
FLUSH PRIVILEGES,确保内存权限与磁盘表一致 - 从库处于
STOP SLAVE状态,避免同步过程中写入冲突
执行命令示例(以同步 mysql 库全部权限表为例):
mysqldump -h master_host -u root -p --skip-triggers --compact --no-create-info \ --where="Host!='localhost'" \ mysql user db tables_priv columns_priv procs_priv proxies_priv > mysql_privs.sql mysql -h slave_host -u root -p mysql <p>关键参数说明:</p>
-
--skip-triggers:跳过系统库中的触发器,避免导入时报错 -
--where="Host!='localhost'":排除本地管理账号(如root@localhost),防止覆盖从库运维通道 -
--no-create-info:不导出CREATE TABLE,避免字段缺失或类型不兼容
用 pt-online-schema-change 类工具做在线权限同步的风险点
Percona Toolkit 的 pt-table-sync 可对比并修复表数据差异,但它对 mysql 库的支持极弱:
- 默认跳过
mysql库(需加--databases mysql强制包含) - 无法处理
user表中加密密码字段(authentication_string)的跨版本哈希差异 - 同步
proxies_priv时若存在嵌套代理关系,容易因主键冲突中断 - 执行期间若其他节点修改权限,会导致短暂不一致,且无事务回滚能力
替代方案更稳妥:SELECT ... INTO OUTFILE 导出主库权限快照,再用 LOAD DATA INFILE 导入目标节点,全程可控、可审计、可重试。
SeaTunnel / DataX 同步 mysql 库的注意事项
这类 CDC 工具默认不采集系统库,必须手动开启:
- SeaTunnel MySQL CDC 连接器需在配置中显式添加
"database-name": "mysql",并确保源端用户有SELECT ON mysql.*权限 - DataX 的
mysqlreader插件需将table配置为["user", "db", "tables_priv"],不能用通配符 - 二者均不解析
GRANT语句,只同步表数据;若目标库存在同名用户,INSERT IGNORE或REPLACE INTO策略需提前约定 - 首次全量同步后,务必关闭 binlog event 捕获,否则
mysql库的频繁内部更新(如slow_log清理)会持续触发无效同步
真正难的不是“怎么同步”,而是“同步时机”和“权限生效顺序”——mysql.user 更新后必须 FLUSH PRIVILEGES,而 mysql.db 变更需配合 FLUSH TABLES 才对已连接会话生效。这些动作无法自动注入到同步流水线里,必须人工介入或封装为部署脚本。











