MySQL主从复制是互联网架构里最常用的读写分离与高可用基座,但很多团队在搭建完复制链路后就默认数据已经一致,直到某天报表对账发现从库金额对不上才意识到问题。MySQL默认的异步复制只保证主库提交后把binlog发给从库,并不保证从库一定应用成功,也不保证主从任意时刻数据相同。要保证一致性,需要从复制机制、校验手段和修复工具三个层面系统性地做工作。

一、MySQL主从复制为何会出现不一致
在标准的异步复制中,主库完成事务提交并将binlog刷盘后,立即返回客户端成功,dump线程把binlog推送给从库的IO线程,从库写入relay log再由SQL线程回放。这个过程里任何一环出错都可能引发偏差。例如主库执行了一条基于非确定性函数的语句,像UUID()或NOW(),在从库回放时得到不同结果;又或者从库被误开了可写权限,运营人员直接连从库改了某条配置,主库完全不知情。
网络闪断也会导致问题。如果从库SQL线程在回放某条更新时因为唯一键冲突而停止,而监控没有及时告警,后续主库的新数据就不会继续同步,从库就停留在错误点之前。此外,使用statement格式的binlog在复杂存储过程场景下更容易出现主从执行差异,而row格式虽安全却会带来日志量膨胀。理解这些根因,才能针对性选择校验与防护方案。
二、通过半同步与GTID降低不一致概率
要从机制上减少不一致,首先应评估是否启用半同步复制。传统异步复制下主库不等待从库确认,而半同步要求至少一个从库接收并写入relay log后再返回提交成功,这样可避免主库宕机后已提交事务彻底丢失。配置方式是在主从分别安装 semisync 插件并设置rpl_semi_sync_master_enabled=1。需注意半同步不是全同步,它只保证relay log落盘,不保证SQL线程已回放,因此仍可能存在极短暂延迟。
另一个关键特性是GTID(全局事务标识)。开启GTID后,每个事务都有唯一ID,从库记录已执行的GTID集合,发生故障切换时新主只需比对集合即可续传,避免传统基于文件偏移量容易找错点的问题。以下示例展示启用GTID的主从关键参数:
-- 主库与从库 my.cnf 核心配置 [mysqld] server-id=1 log-bin=mysql-bin binlog-format=ROW gtid_mode=ON enforce_gtid_consistency=ON rpl_semi_sync_master_enabled=1 rpl_semi_sync_slave_enabled=1
使用GTID后,搭建从库不再需要手动指定master_log_file和master_log_pos,直接用MASTER_AUTO_POSITION=1即可,大幅降低人为偏移错误。不过半同步在从库负载高时会拖累主库写入吞吐,需要结合业务容忍度权衡。
三、用pt-table-checksum定期校验一致性
无论机制多完善,长期运行的集群仍建议做主动校验。Percona Toolkit里的pt-table-checksum是业界标准工具,它把每张表分块,在主库对每块数据计算CRC32哈希,同时通过复制把校验SQL传到从库执行,再从库查自身哈希与主库对比。由于基于binlog复制,从库计算的应该是同一份数据,若结果不同则说明该块不一致。
基本用法如下,其中h=主库IP,u为账号,--databases指定库名,--replicate指定存放结果的表:
pt-table-checksum h=192.168.0.1,u=root,p=pass --databases=shop --replicate=percona.checksums --no-check-binlog-format --recursion-method=hosts
执行后工具会输出每张表的DIFFS列数值,非0即代表发现差异块。需要注意它必须在主库运行,且用户需有相应权限;对超大表应调小--chunk-size避免长事务。该工具只报告差异,不修改数据,因此非常适合生产环境定时巡检,比如每天低峰期跑一次并将结果汇入监控。
四、用pt-table-sync安全修复差异
当checksum指出某表不一致,下一步是修复。pt-table-sync能生成让从库追上主库的变更语句,它先比对行级数据,再输出或执行REPLACE或DELETE。强烈建议第一次先加--print查看将要执行的SQL,确认无误后再用--execute。示例如下:
# 先打印修复语句观察 pt-table-sync h=192.168.0.1,u=root,p=pass h=192.168.0.2,u=root,p=pass --databases=shop --tables=orders --print # 确认后真正执行 pt-table-sync h=192.168.0.1,u=root,p=pass h=192.168.0.2,u=root,p=pass --databases=shop --tables=orders --execute
该工具默认以主库为准覆盖从库,因此绝不可反过来把从库当源。对正在提供读服务的从库,大量REPLACE可能引发锁等待,应在维护窗口操作。修复完建议立刻再跑一次checksum验证DIFFS归零。对于核心金融表,更稳妥的做法是在应用层做双写核对,而非单纯依赖同步工具。
五、应用层与监控的辅助保障
技术工具之外,规范也非常重要。从库应设为super_read_only=ON防止人为直写;ORM框架里把分析查询严格路由到从库,写操作只走主库。监控方面,除了Prometheus抓取Seconds_Behind_Master或GTID差距,还应把pt-table-checksum的DIFFS指标报警出来,做到不一致可被发现、可量化。
总结来看,保证MySQL主从数据一致性不是单点功能,而是复制模式选型、定期校验、差异修复与权限管控的组合工程。中小业务用ROW+GTID+异步足够,配合每周checksum;核心链路再加上半同步与每日校验,可把风险压到最低。只有把一致性当作持续过程而非一次性配置,复制架构才真正可靠。
MySQL主从复制数据一致性pt-table-checksum修改时间:2026-08-01 09:30:30