mysql主从复制中权限未同步的根本原因是mysql.user表变更默认不写binlog,尤其5.7及以前grant不记录,8.0+需确保log_bin=on且未忽略mysql库;必须用create user+grant,禁用直接insert。

MySQL主从复制中权限冲突的根本原因,不是你没给从库授权,而是权限压根没同步过去——mysql.user 表的变更默认不写 binlog,尤其在 5.7 及更早版本。
为什么 GRANT 在主库执行后,从库查不到用户
主库执行 GRANT 后,从库运行 SELECT user,host FROM mysql.user 返回空,或 SHOW GRANTS FOR 'u'@'h' 报 ERROR 1141,说明权限未落地。这不是缓存没刷新,而是 binlog 根本没记录这次授权。
- 5.7 及以前:
GRANT默认不记入 binlog,除非显式开启log_bin_trust_function_creators=1且binlog_format为ROW或MIXED - 8.0+:默认记录,但前提是
log_bin=ON,且没配置replicate_ignore_db=mysql - 检查是否跳过
mysql库:SHOW SLAVE STATUS\G中看Replicate_Ignore_DB字段;或查performance_schema.replication_applier_configuration
必须用 GRANT,别碰 mysql.user 表
直接 INSERT INTO mysql.user 不仅不会触发权限重载,还极大概率导致 binlog 格式错误、从库回放失败,甚至引发 GTID 不一致。
- 正确做法:先
CREATE USER,再GRANT,例如:CREATE USER 'reporter'@'%' IDENTIFIED BY 'pwd';<br>GRANT SELECT ON db.* TO 'reporter'@'%';
-
GRANT是原子性 DDL,能生成可回放的 binlog 事件;执行后无需手动FLUSH PRIVILEGES - 严禁写法:
INSERT INTO mysql.user (Host,User,authentication_string) VALUES ('%','u',PASSWORD('p'));—— 字段顺序、密码字段名(authentication_stringvspassword)、加密方式、过期策略全都不兼容
8.0+ 角色与 GTID 下的特殊注意事项
8.0 引入的 CREATE ROLE 和角色授权也走 binlog,但要求主从版本一致,否则从库因语法不识别而中断复制。
- GTID 模式下,权限变更事务必须完整回放;若报
ERROR 3547 (Role does not exist),说明该角色在从库缺失,不能跳过,而应确认主库已执行CREATE ROLE且对应 GTID 已传到从库 - 关键配置必须双端对齐:
gtid_mode=ON、enforce_gtid_consistency=ON、binlog_format=ROW - 从库延迟大时,可酌情执行一次
FLUSH PRIVILEGES确保内存权限即时生效(仅辅助,非替代方案)
权限同步是隐式过程,不像数据表那样有明显日志可见;最容易被忽略的是 replicate_ignore_db=mysql 这个配置——它像一道静默的防火墙,把所有权限变更都拦在了门外。











