mha故障切换后mysql.user权限不自动同步,因mysql默认过滤mysql库binlog、grant等ddl不记录,需人工导出sql并在新主执行set sql_log_bin=0后导入。

直接说结论:MHA故障切换后,mysql.user 表权限不自动同步,新主库的权限状态停留在切换前快照,旧主库恢复后若直接重做主从,会因权限缺失导致复制中断或应用连接失败。
为什么 mysql.user 不随主从复制自动同步?
MySQL 的权限表(如 mysql.user、mysql.db)默认不走 binlog 复制,除非显式启用 replicate_wild_ignore_table 的反向排除,或更常见的是——根本没开启对系统库的二进制日志记录。
常见错误现象包括:
- 切换后应用报错
Access denied for user 'app'@'%' (using password: YES),但账号明明在旧主上存在 - 从库执行
SHOW GRANTS FOR 'app'@'%'返回空,而旧主上能查到 - 旧主恢复为从库后,IO线程报错
Got fatal error 1236 from master,实际是权限变更语句(如CREATE USER)未被新主记录进 binlog
根本原因在于:mysql 库默认被 MySQL 排除在基于语句(SBR)或行(RBR)复制之外;即使开启了 log_bin,也不等于 mysql 库的操作会被记录。
log_bin_trust_function_creators 和 binlog_format 不解决权限同步问题
这两个参数常被误认为和权限有关,其实完全无关:
-
log_bin_trust_function_creators只影响存储函数/触发器是否允许写入 binlog,与权限表无关 -
binlog_format(ROW/STATEMENT)决定 DML 如何记录,但 DDL(如GRANT、CREATE USER)在STATEMENT模式下本应记录,前提是没被过滤
真正起作用的是:replicate_ignore_db=mysql(默认开启)、replicate_do_db 未包含 mysql、或 skip-log-bin 在从库启动时意外生效。
实操:三步补全权限一致性
必须人工介入,不能依赖 MHA 自动处理。推荐顺序执行:
- 在旧主宕机前,定期导出权限:用
mysqldump --no-data --skip-extended-insert mysql user db tables_priv procs_priv生成可读 SQL,存到共享路径或 Git - 故障切换后,立刻在新主上执行该 SQL(注意先
SET sql_log_bin=0,避免循环写入 binlog) - 旧主恢复为从库前,先用
mysql_upgrade(仅限版本升级场景),再手动RESET SLAVE ALL,然后重新CHANGE MASTER TO,并确认SHOW SLAVE STATUS\G中Seconds_Behind_Master归零且无sql_slave_skip_counter痕迹
如果已启用半同步复制,GRANT 类语句在新主上执行后会强制等待至少一个从库落盘,但这不解决“旧权限未同步”问题,只防止“新权限不同步”。
最容易被忽略的点
权限同步不是“一次配置永久生效”的事。每次通过 CREATE USER、DROP USER、ALTER USER 或 phpMyAdmin/Navicat 等 GUI 工具修改权限后,都必须重新导出并分发到所有节点——MHA 不监听 mysql 库变更,也不触发任何 hook。你看到的“自动切换”,只针对数据和复制拓扑,不包括元数据一致性。











