MySQL系统库默认不会自动同步,因binlog_ignore_db通常忽略mysql库,且权限操作在statement格式binlog中易失真、从库read_only限制写入;需手动导出导入或其它人工干预方案。

MySQL 主从同步时,mysql 系统库(含用户、权限、角色等元数据)默认**不会自动同步**。这是设计使然:主库的权限变更属于 DDL 操作,虽会写入 binlog,但 binlog_do_db 或 replicate-do-db 通常只配置业务库,mysql 库被显式忽略;即使没忽略,MySQL 8.0+ 的权限表(如 mysql.user)使用事务型引擎(InnoDB),而部分权限操作(如 CREATE USER)在 binlog 中以 statement 格式记录,可能因上下文缺失导致从库执行失败。
为什么不能直接让 mysql 系统库走常规复制
常见错误现象:GRANT 后从库查不到新用户、SHOW GRANTS FOR 'xxx'@'%' 报错、从库登录报 Access denied。根本原因是:
-
mysql库默认在主库的binlog_ignore_db = mysql列表中(几乎所有教程都这么配) - 即使去掉该配置,MySQL 5.7+ 对
mysql库的 DML/DDL 有特殊处理逻辑,SQL 线程可能跳过或静默失败 - MySQL 8.0 引入了角色(roles)、密码历史、账户锁定等新字段,
mysql.user表结构更复杂,statement 格式 binlog 容易失真 - 从库若开启
read_only=1(推荐做法),mysql库的写入会被拒绝,即使 binlog 被读取也无法执行
正确同步权限信息的三种实操路径
必须人工介入,没有“开箱即用”的自动方案:
-
手动导出导入(最稳妥,适合低频变更):主库执行
mysqldump --single-transaction --skip-triggers --databases mysql > mysql_privs.sql,清理掉mysql库中与复制无关的表(如general_log、slow_log),再在从库停掉 SQL 线程后导入:mysql -
在从库复刻主库权限语句(推荐用于 MySQL 8.0+):主库运行
SELECT CONCAT('CREATE USER ''',user,'''@''',host,''' IDENTIFIED WITH ',plugin,' AS ''',authentication_string,''';') FROM mysql.user WHERE user NOT IN ('mysql.infoschema','mysql.session','mysql.sys');,再对每个用户补GRANT语句;注意过滤系统内置账户,且需在从库用SET SQL_LOG_BIN=0;关闭 binlog 再执行,避免循环写入 -
用 pt-show-grants 工具(DBA 级别):Percona Toolkit 的
pt-show-grants --host=master_host --user=root --password=xxx可生成可重放的GRANT语句,直接在从库执行即可;它能自动处理角色、SSL、资源限制等细节,比手写 SQL 更可靠
server-id 和 replication 用户权限的硬性要求
权限账号本身必须满足两个前提,否则连复制链路都建立不了:
- 主库上创建的复制用户(如
'repl'@'%')必须明确授予REPLICATION SLAVE权限,GRANT OPTION不是必需的,但若要支持LOAD DATA FROM MASTER(已废弃)则还需FILE和SELECT - 主库和从库的
server-id值必须全局唯一,且不能为 0;若两台机器的server-id相同,从库启动START SLAVE时会报错ERROR 1236 (HY000): Could not open log file,因为 dump 线程无法区分目标 - 从库配置中
CHANGE MASTER TO的MASTER_USER必须与主库上创建的用户名、主机名(@'ip_or_net')完全一致,大小写敏感;例如主库建的是'repl'@'192.168.1.%',从库就不能填'repl'@'%'
真正麻烦的不是配置步骤,而是权限同步的“时机”——你永远没法保证主库刚加了一个用户,从库就立刻拥有同等权限。生产环境建议把权限变更纳入发布流程:先改主库,再手工同步到所有从库,最后验证连接与授权。漏掉一台从库,就可能在线上触发不可预知的访问失败。


















