mysql组复制不自动同步mysql系统库(如user、db表),因权限操作被硬编码为元数据变更而不写入binlog,故create user/grant等不生效;唯一可行方案是在primary节点导出标准化grant语句并人工分发至其他节点执行。

MySQL组复制(Group Replication)不自动同步 mysql 系统库,包括用户权限表(如 mysql.user、mysql.db),无论是否启用 binlog 或 gtid_mode,权限变更都不会被复制。这是硬编码限制,不是配置疏漏。
为什么 CREATE USER 和 GRANT 在组复制中不生效
MySQL 将权限操作视为“元数据变更”,而非普通 DML/DDL 事务。即使在组复制模式下启用了 binlog 和 gtid_mode=ON,CREATE USER、GRANT、DROP USER 等语句仍被跳过写入 binlog,因此不会广播到组内其他节点。
-
FLUSH PRIVILEGES不产生任何 binlog 事件,仅刷新本地内存缓存 - 手动
INSERT INTO mysql.user会被拒绝(MySQL 5.7+)或静默失败(部分旧版本) - 启用
enforce_gtid_consistency=ON后,直接修改系统表会触发ERROR 1786 (HY000):Statement violates GTID consistency
组复制中同步权限的唯一可行路径
必须放弃“自动复制权限”的预期,改用人工分发 + 统一执行的模式。核心是:所有权限变更只在一个节点(通常选 primary 节点)执行,生成可重放的 SQL,再分发到其余节点执行。
- 使用
pt-show-grants(Percona Toolkit)导出标准化GRANT语句:pt-show-grants --host=primary_node --user=root --password=xxx > grants.sql - 清洗输出:删除
SET PASSWORD等非幂等语句,保留纯CREATE USER和GRANT行 - 在其余节点上逐条执行:
mysql -h node2 -u root -p - 每个节点执行后都必须运行
FLUSH PRIVILEGES—— 该命令不复制,必须显式执行
组复制下权限同步容易踩的坑
权限不同步的问题往往在 failover 或角色切换后才暴露,但修复窗口极小。常见陷阱包括:
- 误以为
log_slave_updates=1能让组内节点互相同步权限 —— 组复制不走 slave thread,该参数无效 - 在 secondary 节点上直接执行
GRANT并认为它会传播 —— 实际只影响本节点,且可能因只读模式被拒绝 - 用
mysqldump mysql导出再导入 ——mysql库含内部哈希字段(如plugin、authentication_string),跨版本或跨插件(caching_sha2_passwordvsmysql_native_password)导入会失效 - 忽略
CREATE USER的IDENTIFIED WITH子句 —— MySQL 8.0+ 默认认证插件不兼容旧客户端,必须显式指定
权限同步不是部署阶段的一次性动作,而是持续运维责任:只要任意节点执行了权限变更,就必须立刻将对应 GRANT 语句同步到所有组成员并执行 FLUSH PRIVILEGES。没有后台机制兜底,也没有隐式触发条件。











