mysql集群账号不同步的典型表现是节点a执行create user或grant成功,但连接节点b时提示access denied,或mysql.user表记录不一致;根本原因是mysql原生集群默认不复制mysql系统库,其dml/ddl操作被硬编码跳过binlog,无法通过复制同步。

MySQL集群账号不同步的典型表现
你执行了 CREATE USER 或 GRANT,在节点A上成功,但连接节点B时提示 Access denied for user;或者用 SELECT * FROM mysql.user 查,各节点用户记录不一致。这不是权限没生效,而是 MySQL 原生集群(如 Group Replication、InnoDB Cluster)默认不复制 mysql 系统库——它被明确排除在事务复制之外。
为什么不能靠主从复制自动同步账号
MySQL 的复制机制(包括 GTID 和基于行的复制)默认跳过 mysql 库的 DML/DDL 操作,这是硬编码行为,不是配置能打开的。哪怕你在主节点执行 CREATE USER 'u'@'%' IDENTIFIED BY 'p',这条语句根本不会进入 binlog,自然不会传到从节点。
-
mysql.user表是 MyISAM 引擎(即使 8.0+ 改为 InnoDB,逻辑上仍被隔离) - 复制过滤规则中,
replicate-ignore-db=mysql是默认隐含行为 - Group Replication 更严格:只复制
INFORMATION_SCHEMA和PERFORMANCE_SCHEMA的部分元数据,mysql库完全不参与组通信
真正可行的账号同步方式(非自动化)
没有“一键同步账号”的安全方案。必须人工或脚本驱动,在所有节点上逐条执行相同授权语句。关键是保证语句幂等且顺序可控。
- 用
CREATE USER IF NOT EXISTS+GRANT ... WITH GRANT OPTION组合,避免重复创建报错 - 所有节点执行前,先统一用
SET sql_log_bin = 0关闭日志(仅限当前会话),防止语句又被写入 binlog 循环复制 - 优先使用主机名或 IP 段(如
'app'@'10.20.%')而非'%',减少因 DNS 解析差异导致的权限不一致 - 8.0+ 必须注意
authentication_plugin:如果节点间插件不一致(如有的用caching_sha2_password,有的还用mysql_native_password),即使账号存在也会认证失败
ProxySQL 或中间件层做权限抽象的现实约束
有人想绕过数据库层,用 ProxySQL 的 mysql_users 表统一管理账号。这确实能屏蔽后端节点差异,但只是“连接路由层”的权限,不是真正的 MySQL 权限。
- ProxySQL 不校验 SQL 内容,无法替代
GRANT SELECT ON db.t这类细粒度控制 - 一旦绕过 ProxySQL 直连某个节点(比如运维排查),权限模型立即失效
-
mysql_users表本身也需要手动同步到所有 ProxySQL 实例,没解决本质问题
复杂点在于:账号同步不是技术能不能做,而是“谁负责触发、何时触发、如何验证”。每次加新账号,必须有明确 checklist 覆盖全部节点,漏一个就等于留后门。










