mysqldump导出须加--single-transaction保障innodb一致性,myisam需--lock-all-tables或停写;导入8.0时需临时禁用严格sql_mode防日期错误,并校验外键与自增id。

mysqldump 导出时没加 --single-transaction,主从或写入场景下数据不一致
旧版 MySQL(如 5.6)默认引擎是 MyISAM,新版(8.0+)默认是 InnoDB,但很多老库仍混用。如果导出时不加 --single-transaction,mysqldump 会用表级锁(尤其对 MyISAM 表),导致导出期间新写入丢失或部分表状态错位。
实操建议:
- 只要库中至少有一张 InnoDB 表,就务必加上
--single-transaction—— 它靠 MVCC 快照保证一致性,不锁表 - MyISAM 表无法被
--single-transaction保护,必须配合--lock-all-tables(但会阻塞写入),或提前停写 - 如果不确定引擎类型,先查:
SELECT table_name, engine FROM information_schema.tables WHERE table_schema = 'your_db';
导入时报错 ERROR 1067 (42000): Invalid default value for 'xxx'
这是 MySQL 5.7 升级到 8.0 最典型的兼容性坑:8.0 默认启用 sql_mode=STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,而旧库导出的建表语句里可能有 DEFAULT '0000-00-00' 这类非法日期值。
实操建议:
- 导入前临时放宽模式:
mysql -u root -p --init-command="SET sql_mode=''" your_db - 更稳妥的做法是在导出时就过滤掉非法默认值:
mysqldump --skip-create-options ...,再手动补上兼容的DEFAULT CURRENT_TIMESTAMP等 - 别依赖
--compatible=mysql40,它只改语法,不修数据语义
字符集乱码:导出用 utf8,导入后中文变问号
MySQL 的 utf8 实际是 utf8mb3,不支持 emoji 和部分生僻汉字;而 8.0 默认用 utf8mb4。如果导出时没显式指定字符集,mysqldump 会按服务端默认(可能是 latin1 或 utf8)读取,再以同样编码写入文件 —— 中间一转就丢字。
实操建议:
- 导出必须带:
mysqldump --default-character-set=utf8mb4 -u user -p db_name > dump.sql - 导入时也得指定:
mysql --default-character-set=utf8mb4 -u user -p db_name - 检查源库实际字符集:
SHOW CREATE DATABASE db_name;和SHOW CREATE TABLE t1;,别只信配置文件里的character_set_server
大库导出卡住或超时,mysqldump 进程莫名中断
mysqldump 是单线程、全内存缓冲的工具,面对百 GB 级库,容易因网络超时、内存溢出、或服务器 kill 掉长时间连接而失败。尤其在跨版本迁移时,新版 server 可能对旧协议连接更敏感。
实操建议:
- 加超时兜底:
mysqldump --net_read_timeout=3600 --net_write_timeout=3600 --connect-timeout=3600 ... - 拆表导出(适合可停机场景):
mysqldump --no-create-info --databases db_name --tables t1 t2 > data.sql,避免单文件过大 - 禁用进度提示(减少干扰):
--skip-comments --skip-triggers --skip-routines,只导核心数据结构
真正麻烦的是外键约束和自增 ID 冲突 —— 这些不会报错,但会导致后续插入失败或主键重复,得在导入后立刻校验 SHOW CREATE TABLE 和 SELECT AUTO_INCREMENT FROM information_schema.tables。











