迁移过程如何避免数据不一致 利用强一致性备份方案实战案例|Duuu笔记
mysqldump加--single-transaction不保证强一致,仅对InnoDB表有效,且依赖REPEATABLE READ隔离级别;MyISAM表、DDL操作或隔离级别变更均破坏一致性。
mysql
dump 加
--single-transaction
不等于强一致
很多人以为加了
--single-transaction
就能拿到全库一致性快照,实际不是——它只对 InnoDB 表生效,遇到 MyISAM 表、临时表、或者备份中途有 DDL(比如
ALTER TABLE
),快照就失效了。更关键的是,
--single-transaction
依赖事务隔离级别为
REPEATABLE READ
,而某些 ORM 或中间件会悄悄改隔离级别,导致 dump 出来的时间点不统一。
实操建议:
先用
SELECT ENGINE, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db';
检查是否混用引擎
备份前显式执行
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
如果存在 MyISAM 表,必须配合
--lock-all-tables
(会锁写),不能只靠
--single-transaction
避免在备份窗口内执行任何 DDL;可用
SHOW PROCESSLIST
监控长事务阻塞
GTID +
mysqldump --set-gtid-purged=ON
才能准确定位起点
单纯导出 SQL 文件,恢复后无法知道这条数据对应主库哪个 GTID,也就没法做后续的增量同步或校验。漏掉
--set-gtid-purged=ON
(或设为
OFF
)会导致生成的 dump 文件里没有
SET @@GLOBAL.GTID_PURGED
语句,恢复到新实例后 GTID 集为空,binlog 位置完全脱钩。
实操建议:
务必确认源库已开启
gtid_mode=ON
且
enforce_gtid_consistency=ON
dump 命令中显式加上
--set-gtid-purged=ON
(默认值在新版 MySQL 中已是
AUTO
,但行为不稳定,必须显式声明)
检查 dump 文件开头是否有类似
SET @@GLOBAL.GTID_PURGED='a1b2c3e4-5678-90ab-cdef-1234567890ab:1-100';
的行
恢复时目标实例也需开启 GTID,且
gtid_executed
必须为空(否则报错
GTID_PURGED can only be set when GTID_EXECUTED is empty
)
用
pt-table-checksum
校验前,先停写或切读写分离流量
pt-table-checksum
本身不锁表,但它依赖主从复制延迟接近零才能比对准确。如果迁移后刚切流,应用还在往旧库写、新库靠延迟同步,checksum 结果全是“不一致”,但这不是数据问题,是时间差问题。
实操建议:
校验前确保主从延迟
Seconds_Behind_Master = 0
,且持续稳定 30 秒以上
线上环境必须将写流量切到新库后再启动校验;若做不到,至少把旧库设为
READ_ONLY=1
避免在校验期间执行大事务或批量更新,它们会拖慢 checksum 分块扫描
校验结果中
Differences
列非 0 才真要处理;
Chunk CRC mismatches
可能只是网络抖动导致重试,别一看到就 panic
备份文件传输和导入过程中的隐性截断风险
MySQL 默认
max_allowed_packet
是 4MB,而 mysqldump 导出的大 BLOB 字段、长 JSON 或注释可能单行超限。FTP、SCP、甚至某些 shell 管道(如
gzip | mysql
)在传输中若未设置二进制模式,可能把
\r\n
转成
\n
,导致导入时语法错误或字段截断。
实操建议:
导出时加
--max-allowed-packet=512M
,导入时 mysql 客户端也加同样参数
传输用
rsync -av --compress
或
scp -o Compression=yes
,避免用普通 FTP
导入前先用
head -n 100 your.sql | grep -E "INSERT INTO|VALUES" | wc -l
粗略看首百行是否结构正常
导入命令末尾加
2>&1 | grep -i "error\|warning"
实时捕获关键异常,别等跑完才发现失败
真正难的不是备份命令怎么写,而是搞清每个参数背后依赖的数据库状态——比如 GTID 是否干净、引擎是否统一、写入是否真正停止。这些状态看不见,但一漏就导致一致性崩塌,而且很难回溯。
