同步mysql时必须跳过mysql库,否则会覆盖生产环境权限表;dump需排除权限表或仅导业务库,禁用grant语句,权限变更须走独立版本化sql脚本并人工审批。

同步时跳过 mysql 库是最基本且必须的操作
直接同步整个实例(如用 mysqldump --all-databases 或物理备份恢复)会把 mysql 库里的 user、db、tables_priv 等权限表一并覆盖,导致生产环境账号权限被开发库“洗掉”——这是最常见也最危险的权限错乱来源。
实操建议:
- 用
mysqldump时明确排除:mysqldump --databases db1 db2 db3 --ignore-table=mysql.user --ignore-table=mysql.db ...(注意:--ignore-table对--all-databases无效,必须显式列出业务库) - 更稳妥的做法是只 dump 业务库:
mysqldump --databases app_db billing_db audit_log,完全不碰mysql库 - 若用
mydumper,加--exclude="mysql.*";用Percona XtraBackup恢复时,务必用--export+innodb_tablespaces方式单库恢复,避免全实例覆盖
GRANT 语句不能靠 dump 还原,要单独管理
开发库导出的 mysqldump 文件里若含 GRANT 语句(比如加了 --skip-triggers --routines 但忘了关 --add-drop-user),恢复时会执行这些语句,覆盖生产账号权限。
实操建议:
- dump 时不生成
GRANT:mysqldump --no-create-info --skip-triggers --skip-routines --skip-extended-insert your_db - 所有账号与权限必须走独立的、版本受控的 SQL 脚本(例如
prod-grants.sql),在生产环境手动或通过 CI/CD 执行,不随数据同步流程混入 - 检查 dump 文件头部是否含
CREATE USER或GRANT:用head -n 50 dump.sql | grep -E "(CREATE USER|GRANT)"
开发库的 sql_mode 和字符集可能污染生产
开发环境常设宽松的 sql_mode(如去掉 STRICT_TRANS_TABLES),或用 utf8mb4_0900_as_cs 等新校对规则。如果 dump 文件里有 SET sql_mode=... 或 COLLATE 显式声明,恢复时可能改变生产会话行为或索引比较逻辑。
实操建议:
- dump 时加
--skip-set-charset --no-tablespaces,并确认没带--set-gtid-purged(除非真在用 GTID) - 在目标库执行前,先运行
SET SESSION sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';,再 source dump 文件 - 检查开发库的
character_set_database和collation_database是否与生产一致:SELECT @@character_set_database, @@collation_database;
用 pt-table-sync 做行级比对时也要绕开权限表
即使不用全库 dump,改用 pt-table-sync 同步特定表,如果误将 mysql.user 加入同步列表,它会按主键或唯一键直接 UPDATE/INSERT 权限行,结果一样是覆盖生产权限。
实操建议:
-
pt-table-sync默认不处理mysql库,但必须显式指定--databases限定范围:pt-table-sync --databases=app_db h=dev_host h=prod_host - 加
--print先看它打算执行哪些语句,确认输出里没有UPDATE `mysql`.`user`类操作 - 永远不要对
mysql库运行pt-table-sync,哪怕只是测试
真正麻烦的不是“怎么跳过 mysql 库”,而是权限变更本身缺乏审计闭环——开发改了自己库的账号,却没人确认这些改动是否该上生产、是否和现有策略冲突。自动化同步管道里,权限永远得是手动审批+独立部署的环节。











