能保证InnoDB表一致性:通过REPEATABLE READ事务获取快照,但不适用于MyISAM;不阻塞DDL,需避免dump期间执行ALTER等操作。

mysqldump 加 --single-transaction 能否保证一致性?
在 InnoDB 表上,mysqldump --single-transaction 是常用做法,它通过开启一个 REPEATABLE READ 事务来获取一致快照。但注意:这只对 InnoDB 有效,MyISAM 表仍会锁表;且该选项不阻塞 DDL(如 ALTER TABLE),若迁移过程中有人执行 DDL,可能导致 dump 失败或不一致。
实操建议:
- 确认所有表都是 InnoDB 引擎:
SELECT table_name, engine FROM information_schema.tables WHERE table_schema = 'your_db'; - 避免在 dump 期间执行 DDL 操作,尤其是涉及目标表结构变更的命令
- 若库中混有 MyISAM 表,必须改用
--lock-all-tables或停写
使用 mysqlbinlog + GTID 做增量同步时如何校验一致性?
GTID 模式下,主从位点可精确比对,但迁移后容易忽略「从库是否已追平」这个关键判断。仅靠 SHOW SLAVE STATUS\G 中的 Retrieved_Gtid_Set 和 Executed_Gtid_Set 是否相等还不够——需确认从库已执行完所有主库生成的事务,且没有被跳过(sql_slave_skip_counter 已废弃,但 SET GTID_NEXT 手动注入可能绕过复制)。
实操建议:
- 迁移前记录主库当前 GTID:
SELECT @@global.gtid_executed; - 从库执行
SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS('xxx-yyy-zzz:1-1000');等待指定 GTID 集合执行完毕(MySQL 5.7.6+) - 对比主从
gtid_executed输出,注意过滤掉自动注入的匿名事务(如ANONYMOUS类型)
逻辑导出后用 LOAD DATA INFILE 导入,为什么主键冲突或唯一键重复?
常见原因是导出时没禁用外键检查或唯一约束检查,或导入前未清空目标表(残留数据 + 新数据触发冲突)。更隐蔽的是:源库有 INSERT IGNORE 或 ON DUPLICATE KEY UPDATE 逻辑,而 dump 文件里只保留了原始 INSERT,丢失了冲突处理语义。
实操建议:
- 导入前加
SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0;,导入后再恢复 - 确认目标表为空,或用
TRUNCATE TABLE(注意自增 ID 重置)而非DELETE FROM - 若源业务依赖冲突覆盖逻辑,不要直接用 mysqldump,改用
SELECT ... INTO OUTFILE+ 自定义脚本构造带ON DUPLICATE KEY UPDATE的语句
跨版本迁移(如 MySQL 5.7 → 8.0)最容易忽略的兼容性问题
MySQL 8.0 默认启用 sql_mode=STRICT_TRANS_TABLES,而旧版本可能宽松;同时 8.0 移除了 mysql_old_password 认证插件、默认字符集改为 utf8mb4_0900_as_cs。这些都会导致 dump 导入失败或数据截断。
实操建议:
- 导出时显式指定兼容模式:
mysqldump --compatible=mysql40 --default-character-set=utf8mb4 - 导入前在目标库执行:
SET sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';(根据实际需要调整) - 检查字段长度:如
VARCHAR(255)在 utf8mb4 下实际占 1020 字节,可能超索引长度限制(InnoDB 单索引最大 767 字节,或 3072 字节取决于innodb_large_prefix)
真正难的不是导出或导入本身,而是确认「此刻的数据状态」是否被完整捕获——比如长事务未提交、半完成的批量更新、或者应用层缓存掩盖了底层不一致。做校验时别只看行数,要抽样比对关键业务字段的 CRC32 或 SHA2 值。










