MySQL主从权限不同步的根源是GRANT操作未写入binlog,因默认忽略mysql库或binlog未启用:5.7及以前GRANT不记日志,8.0+需log_bin=ON且replicate_ignore_db不含mysql;直接改mysql.user表会导致复制中断。

权限不一致导致的复制中断,本质不是账号没建,而是权限变更没进 binlog —— 从库根本收不到,自然查不到用户、连不上、报 Access denied for user。
为什么 GRANT 在主库执行了,从库还是没权限
MySQL 主从默认不把 mysql.user 表的变更写入 binlog。5.7 及更早版本中,GRANT 语句默认不记日志;8.0+ 虽默认记录,但前提是:log_bin=ON 且没配 replicate_ignore_db=mysql。
-
SELECT user,host FROM mysql.user在主库有结果、从库返回空,就是典型信号 -
SHOW GRANTS FOR 'u'@'h'在从库报ERROR 1141,说明权限记录完全缺失 - 检查是否跳过
mysql库:SHOW SLAVE STATUS\G中看Replicate_Ignore_DB字段是否含mysql
必须用 GRANT,别碰 mysql.user 表
直接 INSERT INTO mysql.user 或 UPDATE mysql.user 不仅不会触发权限重载,还极大概率导致 binlog 事件格式异常,从库回放失败甚至中断复制。
-
CREATE USER 'reporter'@'%' IDENTIFIED BY 'pwd'; GRANT SELECT ON db.* TO 'reporter'@'%';—— 这才是正确路径 -
GRANT自动触发FLUSH PRIVILEGES,无需手动执行 - 禁用以下写法:
INSERT INTO mysql.user (Host,User,authentication_string) VALUES ('%','u',PASSWORD('p'));,字段顺序、密码加密方式、过期策略极易出错,且不保证 binlog 正确
主库必须满足的硬性条件
光写对语句不够,底层机制必须打开。否则哪怕你天天 GRANT,从库也永远收不到。
- 主库必须开启 binlog:
log_bin=ON(不能只配log_bin_basename就以为开了) - 禁止忽略
mysql库:replicate_ignore_db配置里不能出现mysql;GTID 模式下还要确认binlog_ignore_db同样未屏蔽 - 主库
my.cnf中建议显式启用:binlog_format=ROW或MIXED,避免 SBR 下权限语句解析歧义 - 验证是否生效:在主库执行
GRANT后,查SHOW BINLOG EVENTS IN 'mysql-bin.0000xx' LIMIT 10,确认能看到Write_rows_v1或Query类型的权限相关事件
最容易被忽略的一点
很多团队在主库开了 log_bin,却忘了检查从库的 replicate_ignore_db 是否继承了主库的忽略规则——尤其当配置是通过 Ansible 或容器模板批量下发时,mysql 库常被无意识加入忽略列表。权限不同步问题,八成卡在这一步。


















