主从数据库数据不一致,十次里有七八次不是复制链路断了,是排查的人顺序搞反了。上来就翻 binlog、跑校验脚本、甚至直接重做全量,折腾一圈问题还在,业务先被拖下水。真正该做的第一件事特别朴素:先搞清楚从库是「没追上」还是「追错了」。这两件事的修法完全相反,方向错了,越修越乱。

主从数据库数据不一致,先分清落后和错位
落后好理解,主库写了,从库还在后面排队,数据只是慢半拍,等一会儿它自己就对上了。错位是另一回事,从库已经追到最新位点了,但追出来的结果跟主库不是一份东西,你等到天亮也不会自愈。判断办法不复杂:主库上手动插一行带时间戳的标记数据,掐着表看它多久出现在从库。几十秒内出现,那是延迟问题;几分钟都不出现,或者出现了但内容被改过,那就是错位。别太信 Seconds_Behind_Source 那个数字,主库没写入的时候它常年显示 0,主库一开始压数据它又突然跳上去,靠它判断早晚要误事。
方向一:复制线程到底卡在哪一步
SHOW REPLICA STATUS 敲下去,先看两个线程的状态。MySQL 8.0.22 之后命令改名叫 REPLICA 了,老版本还得敲 SLAVE,敲错了会让人误以为自己在看一台正常的机器。IO 线程停,多半是网络、账号权限,或者主库的 binlog 已经被 purge 掉,报错里那个 1236 基本就是「你要的位点没了」。SQL 线程停的原因更实在,主键冲突、要更新的行在从库不存在、字段长度不够、字符集对不上,Last_SQL_Error 那句英文一般已经把原因写明白了。见过太多人连这句都不看,直接去搜怎么办,然后照着帖子把从库重做了一遍——原来只是一条重复主键。
方向二:binlog 到从库的路上有没有丢东西
这一类最阴,因为复制状态看着一切正常,两个 Yes 挂着,延迟也是 0,数据就是对不上。第一件事看 binlog_format。老库从旧版本升上来的,很多还留着 STATEMENT。这个格式下,语句里带 NOW()、RAND()、UUID(),或者 LIMIT 不带 ORDER BY,主库和从库执行出来的结果可能不一样,而且不报任何错。改成 ROW 之后稳得多,但也不是万事大吉:replicate-do-db、replicate-ignore-db 这些过滤规则在不同格式下行为有差别,DDL 尤其容易漏;还有临时表、跨库更新,都可能在从库上被悄悄跳过。查这类问题,直接拿 mysqlbinlog 把那个时间段的日志解析出来,跟从库对应时间段的数据摆在一起对,比坐在那儿猜快得多。
方向三:从库上有没有人在偷偷写
有些不一致是反过来的,主库没有的数据从库有。这种八成是从库被人写了:应用读写分离的配置写反、双写开关没关、定时统计任务跑在从库上,再或者是运维为了临时救急直接在从库上 UPDATE 过。read_only=ON 挡不住有 SUPER 权限的账号,得把 super_read_only 也打开,两个一起开才踏实。判断方法很直观,把差异行的分布拉出来看:如果多出来的数据集中在那几张表、集中在某个时间段,基本就是那段时间里有人往里写过东西。
顺序一旦搞反,代价比问题本身还大
最常见的是直接上 pt-table-checksum 做全表校验。这工具本身没毛病,但它对大表算 checksum 的时候会往从库压查询,从库 IO 本来就紧张,业务先跟着抖。还有人一看对不上,二话不说 CHANGE REPLICATION SOURCE 重做全量,几百 G 的库重建几个小时,这期间从库不可用,最后发现差异只有三行。所以顺序应该是:先确认落后还是错位,再看复制线程的报错,再看 binlog 格式和过滤规则,最后才怀疑从库被写。前三步基本是几分钟的事,第四步才需要动工具。
差异行找到了,具体怎么补
行数不多的话,别整库重做。pt-table-sync 可以只补差的那几行,但上生产之前一定加 –dry-run 把语句打出来看看,它是会往主库写东西的,方向搞错了就是拿错数据盖好数据。稳一点的做法是从最近的备份里把这几行捞出来,人工比对完再回补。如果差异比例已经很大,就别纠结单行了,重建从库更省心,用备份加 binlog 追到最新位点,比一行一行修靠谱。补完一定再校验一遍,见过补完没验、第二天报表还是不正确的。
平时怎么让这事儿少发生
几个习惯能省很多事。binlog_format 全站统一成 ROW,别让个别老实例留着 STATEMENT。从库上 super_read_only 打开,应用账号一律不给写权限。复制延迟和 Last_SQL_Error 挂进监控,出问题第一时间知道,别等业务先发现。DDL 变更走统一流程,别在高峰手工 ALTER。低峰期定期跑一次校验,采样就行,不用全表。这些事单拎出来都不难,难的是没人盯着就慢慢松了。
下次再碰到对不上,按这个顺序过一遍:插标记行看延迟、SHOW REPLICA STATUS 看报错、mysqlbinlog 对时间段、查从库写入痕迹,最后才是上工具和重建。这套流程走下来,大部分问题在第二步就停了。真正需要重建从库的场景,比很多人想的少得多。
【版权声明】:本站内容若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!