跨机房mysql迁移必须依赖gtid+row主从复制并用pt-table-checksum校验,因mysqldump--single-transaction仅适用于纯innodb且无ddl的短时场景,无法捕获搬迁窗口期变更,违背rpo=0要求,且存在字符集、环境差异等隐性风险。

异地机房搬迁时,MySQL数据同步的完整性与一致性不能靠“导完再切”来赌,必须依赖 GTID + ROW 格式 binlog 的主从复制链路,并在切换前用 pt-table-checksum 实际比对,否则极易出现隐性不一致。
为什么 mysqldump --single-transaction 不适合跨机房搬迁
它只对 InnoDB 表生效,且要求全程无 DDL;但跨机房场景下,网络延迟会导致 dump 时间拉长,期间若有人执行 ALTER TABLE 或混用 MyISAM 表,快照事务立即失效。更关键的是:mysqldump 导出的是“某个时刻的静态快照”,无法捕获搬迁窗口期产生的任何新变更——这直接破坏 RPO=0 的前提。
- 导出耗时超过 5 分钟后,业务写入已产生大量 binlog,这些变更不会被包含在 SQL 文件中
- 导入目标库是单线程执行 INSERT,100GB 数据可能跑数小时,期间源库持续写入,差距越拉越大
- 字符集、sql_mode、time_zone 等环境差异会 silently 导致字段截断或时间错位,
mysqldump不校验也不报错
GTID 主从复制必须满足的三个硬条件
缺一不可,否则 CHANGE MASTER TO 会失败,或后续 SHOW SLAVE STATUS\G 显示 Retrieved_Gtid_Set ≠ Executed_Gtid_Set。
- 源库开启
gtid_mode=ON且enforce_gtid_consistency=ON(否则非 GTID 事务无法被安全重放) - 源库
binlog_format=ROW(STATEMENT 模式在跨机房因函数/时间/自增等导致从库执行结果不一致) - 目标库初始化时执行
RESET MASTER(清空gtid_purged),否则导入含 GTID 的 SQL 会触发ERROR 1840 (HY000)
如何验证“真追平”,而不是看 Seconds_Behind_Master=0
Seconds_Behind_Master=0 只表示 IO 线程和 SQL 线程没积压,不代表数据内容一致——比如某张表被误删后又重建,从库照样能“追平”,但数据已空。必须用数据级校验工具。
- 运行
pt-table-checksum前,确保目标库已停写(哪怕只停 30 秒),否则校验值随时变动 - 重点检查
Differences列为1的表,它代表分块校验和不匹配,不是简单行数对比 - 若发现差异,用
pt-table-sync --sync-to-master生成修复语句,**不要直接执行**,先人工 review 是否涉及业务关键字段 - 校验过程本身会产生少量负载,建议避开业务高峰,且限制
--chunk-size防止锁表过久
切流前最容易被忽略的三件事
技术方案再稳,运维动作漏一项就可能回滚失败。
- 两机房所有 MySQL 节点必须 NTP 对齐,误差 > 500ms 就会导致 GTID 解析错乱、
pt-table-checksum时间戳比对失准 - 目标库的
auto_increment_offset和auto_increment_increment必须与源库错开(如源库设为 1,2,目标库设为 2,2),避免双写阶段主键冲突 - DNS 或 LB 切流指令发出后,要立刻在源库执行
FLUSH TABLES WITH READ LOCK并SHOW MASTER STATUS记录最终位点——这是唯一能确认“最后一条变更已同步”的证据











