直接用mysqldump -a导出再导入会导致测试库权限冲突或导入失败,因其包含mysql、sys、performance_schema等系统库,覆盖mysql.user表造成账号丢失、触发mysql.db权限冲突、引发sys库版本不兼容报错。

直接用 mysqldump + mysql 命令链最稳妥,但必须加 --single-transaction 和跳过权限/系统库,否则测试库会出权限冲突或导入失败。
为什么不能直接 mysqldump -A 导出再导入?
导出全实例(mysqldump -A)会包含 mysql、sys、performance_schema 这些系统库。测试环境已有用户和权限表,直接导入会导致:
-
mysql.user表被覆盖,原有测试账号丢失或权限错乱 -
mysql.db或mysql.tables_priv冲突,后续建库建表报Access denied -
sys库版本不一致(比如源是 MySQL 8.0.33,测试是 8.0.28),导入失败报错Unknown column 'total_latency' in 'field list'
只导出业务库的正确命令写法
假设你要迁移的业务库叫 order_db 和 user_db,且测试库已存在空库结构(或允许自动创建):
mysqldump -h 源IP -u 用户名 -p密码 --single-transaction --routines --triggers --events --set-gtid-purged=OFF order_db user_db > prod_backup_$(date +%Y%m%d).sql
关键参数说明:
-
--single-transaction:对 InnoDB 表做一致性快照,避免锁表影响生产写入 -
--routines:导出存储过程和函数(如漏掉,测试环境调用会报PROCEDURE not exists) -
--triggers:导出触发器(尤其涉及审计日志类逻辑) -
--set-gtid-purged=OFF:关闭 GTID 信息写入,否则导入时可能报GTID_PURGED can only be set when GTID_EXECUTED is empty - 不加
--databases或-B:避免在 SQL 文件头部生成CREATE DATABASE IF NOT EXISTS,防止测试库名不一致时报错
导入到测试库前必须做的三件事
导入不是把文件丢进去就完事。以下操作缺一不可:
- 确认目标测试库字符集与源库一致:
SHOW VARIABLES LIKE 'character_set_database';,不一致先执行ALTER DATABASE test_db CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; - 删掉备份文件里所有对
mysql库的操作:用sed -i '/^USE `mysql`;/d; /^CREATE DATABASE.*`mysql`/d' prod_backup_*.sql - 导入时不走 root,用测试库专用账号(比如
test_user),并确保它对目标库有CREATE、INSERT、ALTER权限,避免中途因权限中断
大表(>1GB)导入卡住或超时怎么办?
直接 mysql -u test_user -p 容易因网络抖动、max_allowed_packet 不足或事务超时失败。建议分步处理:
- 先临时调大参数:
mysql -u test_user -p -e "SET GLOBAL max_allowed_packet=512*1024*1024; SET GLOBAL innodb_log_file_size=256*1024*1024;" - 拆分大表导出:用
mysqldump --where="1 limit 1000000" db table > table_part1.sql分片导出,再逐片导入 - 跳过外键检查加速导入:
mysql -u test_user -p -e "SET FOREIGN_KEY_CHECKS=0; SOURCE /path/to/prod_backup.sql; SET FOREIGN_KEY_CHECKS=1;"
真正容易被忽略的是:导入后没清空测试库里的旧数据,导致新老数据混在一起;或者没重置自增主键,插入时撞上重复 ID 报错。这些细节比工具选型更决定迁移成败。











