mysqldump 导出时要不要加 --single-transaction
如果源库是 InnoDB 且业务可短暂停写,
--single-transaction是最稳妥的选择。它通过开启一致性快照避免锁表,导出过程不会阻塞 DML(但 DDL 仍会被阻塞)。
不过要注意:
--single-transaction对 MyISAM 表无效,会退化为表级锁;如果库中混用引擎,建议先用
SELECT ENGINE, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db';检查。
常见错误是没关掉自动提交又没加事务控制,导致大表导出中途失败后残留临时文件。 只对 InnoDB 生效,MyISAM 或混合引擎需搭配
--lock-tables或停写 必须配合
--databases或指定库名使用,单独用
--all-databases时也生效 导出前确认
innodb_lock_wait_timeout足够长,否则长事务可能中断 dump
目标 MySQL 版本高于源库时的兼容性风险
高版本 MySQL 默认启用更严格的 SQL 模式(如
STRICT_TRANS_TABLES、
NO_ZERO_DATE),而旧库导出的 SQL 可能含隐式类型转换或非法日期(如
'0000-00-00'),直接导入会报错
Incorrect date value或
Data truncated。
解决方式不是降级目标库,而是导出时加
--compatible=mysql40(或对应旧版本),或导入前在目标库临时设置:
SET sql_mode='';导入完成后再恢复严格模式。 用
SELECT @@sql_mode;分别查源库和目标库的默认模式差异
mysqldump --no-create-info配合
--skip-extended-insert更易定位插入失败的具体行 5.7 升 8.0 时注意
mysql.user表结构变化,不建议直接拷贝系统库
大库(>100GB)迁移时跳过 mysqldump 的替代方案
单纯靠
mysqldump导入百 GB 级数据,I/O 和单线程瓶颈明显,常卡在“Waiting for table flush”或“Repair by sorting”。这时应优先考虑物理复制:
停写源库 →
FLUSH TABLES WITH READ LOCK;→ 记录
SHOW MASTER STATUS;→ 直接拷贝
datadir下对应库的文件夹(含 .ibd/.frm/.isl)→ 在目标机启动 MySQL 前替换数据目录并修正权限 → 启动后执行
ALTER TABLE ... IMPORT TABLESPACE;(仅限独立表空间)。 必须确保源/目标 MySQL 的
innodb_file_per_table开启状态一致 8.0+ 使用数据字典,不再有 .frm 文件,需用
mysqlpump或
mysqlbackup替代 若无法停写,可用
Percona XtraBackup做热备份,但要求目标机安装相同 major 版本的 Percona Server 或兼容版
迁移后验证主从延迟和数据一致性
即使导入成功,也不代表数据完全一致。尤其跨版本迁移后,
CHECKSUM TABLE可能因排序规则或隐式转换返回不同值。更可靠的方式是用
pt-table-checksum(Percona Toolkit)做行级比对,它会自动分块、避开锁表高峰,并生成校验结果表供查询。
主从场景下,还要检查
Seconds_Behind_Master是否归零,以及
SHOW SLAVE STATUS\G中的
Exec_Master_Log_Pos是否与源库
SHOW MASTER STATUS一致。 校验前先在目标库关闭
foreign_key_checks和
unique_checks加速 避免在校验期间执行
OPTIMIZE TABLE或
ANALYZE TABLE,会干扰位置点 若发现不一致,用
pt-table-sync修复,但务必先备份目标库 实际迁移中最容易被忽略的是字符集继承问题:
mysqldump默认按连接字符集导出,如果源库建表时没显式声明
CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,而目标 MySQL 8.0 默认用新 collation,会导致排序行为突变。导出时加上
--default-character-set=utf8mb4并在目标库创建库时显式指定,比事后修复成本低得多。
