镜像站和源站数据不一致,核心解决办法是按“业务影响排序”逐层排查:先定位同步链路是否中断,再校验增量同步机制,最后用全量比对工具修复差异,并建立自动告警防止复发。 多数情况下,这类问题源于同步任务异常、主从切换残留或人为误操作,而不是源站本身数据损坏。
镜像站数据不一致的常见原因定位
先别急着重传数据,花几分钟判断不一致属于哪一类,行业共识认为,超过七成的镜像站同步故障集中在同步进程假死、网络抖动导致的增量丢失、以及磁盘写入延迟,你可以通过以下三方面快速锁定方向。
同步链路状态检查
无论你用的是rsync、MySQL主从复制还是对象存储的跨区域复制,第一步永远是看同步任务本身是否还在跑。
- 登录源站和镜像站的服务器,分别执行
ps aux | grep rsync(以rsync为例),确认进程是否存在。 - 查看同步日志末尾时间戳,如果日志停在几小时前,大概率是进程卡死或OOM被系统杀掉。
- 用
telnet 镜像站IP 端口测试源站到镜像站的网络连通性,排除防火墙或安全组策略变更。
如果同步进程已经死掉,直接重启任务,然后观察差异数据量是否在缩小,这里有个容易踩的坑:很多同步工具默认不删除目标端多余文件,即使进程恢复,旧的脏数据也不会被自动清除。
增量同步与全量同步的差异判断
增量同步依赖binlog、oplog或文件系统的变更记录,如果源站开启了缓存或异步写入,部分数据可能尚未落盘就被增量任务跳过。
- 在源站执行
SHOW MASTER STATUS(MySQL场景),记录binlog文件名和位置。 - 在镜像站执行
SHOW SLAVE STATUS,对比Read_Master_Log_Pos和Exec_Master_Log_Pos是否一致。 - 如果不一致,说明存在relay log重放延迟,此时不要强行跳过错误,先查看
Last_SQL_Error字段,解决导致重放停止的冲突(常见于主键重复或字段长度超限)。
文件同步中的时间戳与权限陷阱
对于静态文件镜像,rsync -avz默认会忽略源端文件的所有者、权限变化,只要文件大小和时间戳一致就认为相同,这会导致内容变了但mtime未变的数据无法同步。
行业共识提醒,只依赖mtime做增量判断的同步方案,在网站文件被程序直接修改(不更新mtime)时必然出现镜像与源站不一致

,建议改用rsync -avz --checksum先做一次全量校验,虽然慢,但能找到所有大小和mtime未变、内容却不同的文件。
镜像站和源站数据不一致怎么修复:分场景操作
搞清楚原因后,按下面三种场景分别处理,实际操作中,混合场景很常见,建议按顺序执行。
同步中断后恢复,差异持续存在
这种情况最普遍,同步任务重启后看似在跑,但镜像站始终追不上源站。
解决步骤:
- 在源站执行完整全量同步,例如
rsync -avz --delete /data/ 镜像站IP:/data/,加--delete是为了清理镜像站上源站已删除的文件。 - 同步期间不要修改源站数据,如果无法停机,先暂停写入服务,或者使用LVM快照、云厂商的磁盘快照作为同步源。
- 全量完成后,紧接着启动增量同步,注意增量任务必须从全量开始的时间点接着记,否则会漏掉全量过程中的新增数据。
实测中有个细节:如果全量同步跑了2小时,期间源站持续有写入,增量同步启动后需要先追2小时的binlog,再追上实时位点,此时镜像站I/O压力会很大,建议临时调低同步并发数。
主从切换后数据错位
高可用架构下,源站发生过故障切换,原主库变成从库,而镜像站还在跟旧主库同步,切换后,新的主库没有及时把缺失的binlog补传给镜像站,或者镜像站积压了大量未执行的relay log。
修复路径:
- 先确认当前真正的源站是哪个,登录数据库执行
SHOW REPLICA STATUS,看Source_Host是否指向正确的源站IP。 - 停止镜像站的从复制进程。
- 在主库执行
FLUSH TABLES WITH READ LOCK,然后SHOW MASTER STATUS记录位置。 - 在镜像站执行
RESET SLAVE,重新设置MASTER_LOG_FILE和MASTER_LOG_POS到刚才记录的位置。 - 解锁主库,启动复制。
这个过程要求业务允许秒级写入停顿,如果业务不能停,建议放弃旧镜像站,重新搭建从库,用xtrabackup --stream=xbstream等物理备份工具做全量恢复,比逻辑备份快得多。
程序逻辑导致的特定数据不一致
比如源站写入时有事务,但同步是异步的,恰好源站事务回滚了,而中间态数据已经被同步到镜像站,或者开发改了代码,新数据多了一个字段,而同步脚本没更新映射关系。
这种问题靠工具没用,需要人工比对,操作建议:
- 抽取全量数据的MD5校验清单,在两端分别生成,源站执行
find /data -type f -exec md5sum {} ; > /tmp/source.md5,镜像站同理,再diff两个文件。 - 对数据库,用
pt-table-checksum(Percona Toolkit)校验每个表的行数和checksum,这是业内常用的开源工具,不需要额外许可。 - 定位到差异表或差异文件后,看是新增、缺失还是内容变化,新增的补传,缺失的在源站删除,内容变化的覆盖同步。

千万别对全量数据直接“无脑覆盖”,如果镜像站有数据是源站没有的,直接覆盖会丢数据,先备份镜像站差异数据,再执行修复。
如何自动化防止镜像站和源站数据不一致
修复一次不难,难的是不再发生,自动化校验要分成两个层次:实时监控和定期巡检。
实时同步状态告警
用监控工具盯住同步任务的延迟指标:
- 数据库场景:监控
Seconds_Behind_Master,超过30秒就告警。 - 文件场景:比较源站和镜像站的最新文件修改时间差,超过5分钟触发告警。
- 对象存储场景:监控
ReplicationLatency云厂商指标。
告警渠道建议直接接钉钉/企业微信机器人,别只发邮件,很多团队的邮件告警根本没人看。
定期全量校验策略
每周执行一次全量比对,放在业务低峰期,比对工具不必很复杂:
- 小数据量(几十GB):直接用
diff -rq或rsync -avzc --dry-run。 - 大数据量(几TB):分批抽样比对,每批随机抽取10%的文件或记录做checksum,如果发现差异再扩大到全量。
- 数据库:每月跑一次
pt-table-checksum,并把结果存档。
重点在于校验结果要自动生成报告并推送给负责人,否则形同虚设。
数据校验工具对比与选择
不同场景下,合适的工具组合能大大节省排查时间。
| 场景 | 推荐工具 | 优点 | 注意点 |
|---|---|---|---|
| Linux文件同步 | rsync + --checksum | 轻量、无额外依赖 | 全量校验耗时较长 |
| MySQL主从 | pt-table-checksum | 支持在线校验,不锁表 | 需要Percona Toolkit环境 |
| Redis多实例 | redis-cli --scan + compare | 无需第三方 | 数据量大时内存占用高 |
| 对象存储跨区域复制 | 云厂商列举API写脚本 | 直接对比ETag | 注意分页和流量费用 |
| 通用数据库 | 自研基于主键的hash比对 | 灵活 | 需要业务停机或只读窗口 |
如果你们公司预算允许,采购商业的数据复制管理平台也是选择之一,但据行业观察,中小团队用开源工具加定时脚本,已经能覆盖九成以上的同步不一致问题。
镜像站数据不一致修复时的注意事项
最后提醒几个实战中的坑,都是真实踩过的:
- 修复操作要在低峰期执行,尤其是涉及全量覆盖时,I/O占用会拖慢源站响应。
- 先记录当前镜像站的差异文件列表,再动手修,万一修错了还能回滚。
- 多套镜像站时,先修离源站最近的节点,核心业务的镜像站通常也在同城IDC,同步延迟低,先修它,再让它作为次级源站同步给远程镜像站。
- 不要依赖云控制台的“一键同步”按钮,这些触发器经常有并发锁限制,数据量大时容易中断。
如果你用的是宝塔面板这类图形运维工具,同步任务异常时,不要只依赖面板日志,直接登录服务器看系统dmesg和cron日志,面板有时会吞掉一些报错信息。
镜像站数据不一致常见问题解答
镜像站和源站数据不一致,可以只删除镜像站的同步日志吗?
不行,同步日志只是记录,不是数据本身,删除日志不会修复数据差异,反而会丢失排查线索,先看日志定位原因,再根据原因决定是全量覆盖还是增量补齐。
为什么源站新上传的文件,镜像站一直不显示?
如果同步进程正常,也没报错,优先检查文件上传是否真的写入了源站的同步目录,有些应用开启了临时文件目录,写入后重命名,同步工具配置了--exclude排除临时文件,就会漏掉最终文件,其次检查同步任务是否只监听目录而不监控子目录,需要加上-r递归参数。
MySQL主从同步的SQL线程报错,是不是直接`SET GLOBAL sql_slave_skip_counter=1`跳过就行?
不要盲目跳过,跳过之前必须确认错误是可忽略的脏数据还是结构变更冲突,主键重复可以用skip_counter跳过,但如果是表结构不一致,跳过后后续所有该表的写入都会继续报错,正确做法是在主库补一个相同的DDL,然后重启SQL线程,或者彻底重建该表的同步关系。
