主从权限不同步的根本原因是GRANT操作未写入binlog:5.7及以前默认不记录,8.0+需log_bin=ON且replicate_ignore_db不含mysql;直接操作mysql.user表会导致复制失败,必须用CREATE USER+GRANT原子语句。

主从权限不同步不是配置漏了,而是 GRANT 没进 binlog —— 从库根本收不到,自然没用户、连不上、报 Access denied。
为什么 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 (42000),说明权限记录完全缺失 - 检查是否跳过
mysql库:SHOW SLAVE STATUS\G中看Replicate_Ignore_DB字段是否含mysql
必须用 CREATE USER + GRANT,别碰 mysql.user 表
直接 INSERT INTO mysql.user 或 UPDATE mysql.user 不仅不会触发权限重载,还极大概率导致 binlog 事件格式异常,从库回放失败甚至中断复制。
- 正确做法是原子性 DDL:
CREATE USER 'reporter'@'%' IDENTIFIED BY 'pwd';+GRANT SELECT ON db.* TO 'reporter'@'%'; -
GRANT自动触发FLUSH PRIVILEGES,无需手动执行 - 若从库延迟大、权限未即时生效,可酌情在从库执行一次
FLUSH PRIVILEGES(仅限紧急确认,非常规操作)
确保 binlog 记录权限变更的硬性条件
光写对语句不够,底层机制必须打开。否则哪怕你天天 GRANT,从库也永远收不到。
- 主库必须开启 binlog:
log_bin=ON(不能只配log_bin_basename就以为开了) - 禁止忽略
mysql库:replicate_ignore_db配置里不能出现mysql;GTID 模式下还要确认binlog_ignore_db同样未屏蔽 - 主库
my.cnf中建议显式启用权限日志(8.0+):binlog_format=ROW+default_authentication_plugin=mysql_native_password(避免插件不兼容) - 验证是否生效:在主库执行
GRANT后,查SHOW BINLOG EVENTS IN 'mysql-bin.0000xx' LIMIT 10,确认能看到Write_rows_v1或Query类型的权限相关事件
最容易被忽略的一点:replicate_ignore_db=mysql 被批量继承
很多团队在主库开了 log_bin,却忘了检查从库的 replicate_ignore_db 是否继承了主库的忽略规则——尤其当配置是通过 Ansible 或容器模板批量下发时,mysql 库常被无意识加入忽略列表。权限不同步问题,八成卡在这一步。
它不报错、不中断复制、Seconds_Behind_Master 看似正常,但新用户就是登不上,SHOW GRANTS 就是空——这种静默失效最难排查。


















