wtf!rds数据同步居然出问题了--小白db的数据修复历程

  由于一次上线操作的数据变更太多,导致执行时间很长!

  由于做手动主从关系,所以操作落在了主库上。

  由于主从关系不是对整个库的操作,所以在有表新增的地方,添加了新的同步关系。

  db变更完成后,就发布代码上线了!

以上是背景!一切看起来都很美好。

  代码上线后,从从库发现数据一直没有,时间在一分分地过去。

  我知道不能再等了,我从后台直接进入主库,查看数据,正常写入!

  我知道是数据同步出问题了!妈蛋,说好的花钱买稳定呢?

  同步出问题了,这让我怎么排查?我又不是dts的开发人员!

不过我还是想了几个方向查一下:

  1. 查看同步任务,检查是否有同步异常日志;
  2. 检查目前的同步状态,是否有异常;
  3. 检查同步流量情况,如果同步正常的话;
  4. 检查监控报警是否存在;
  5. 检查dts服务是否被黑名单了;
  6. 如果实在不行,给阿里云提交工单吧;

针对这几个方向,着实是一个个落实了的。然而,结果是,不得而知。

  1. 同步没有日志,why,可能是日志太多没意义吧!
  2. 没有发现异常,所有监控为空;
  3. 由于我最开始做主从关系时,没进行全量初始化数据,所以初始化状态拦也为空;
  4. 同步流量监控,基本为0,但是这貌似不能说明问题,才怪!
  5. 重新把自己加入到报警人员中,期待出问题时收到消息,不过最终并没有收到过;
  6. 检查ip白名单问题,发现并无异常,而且数据库进程中,也有dts服务存在;
  7. 最终还是给阿里云提交了工单,然而并没有什么卵用,迫在眉睫,还得自己先解决问题!
  8. 怀疑是在做数据结构变更或者新增同步对象时,dts发生了异常,然而怀疑有毛用。反正又不能解决!

  实在没办法,我觉得这个同步任务多半已经挂掉了,所以决定重新搞一个任务。也就是,把原来的同步任务删掉,然后新建一个同步。虽然看到了很多警告,我还是干了,没办法。重新设置任务,想勾选初始化数据和全量同步,结果失败了。原因是,数据表已在目标库中存在,可能存在冲突。

  重新设置同步任务的过程,等待也是让人着急。但不管怎么样,还是看到了同步中的状态,发现从库有数据了,但是仅仅是部分。抽查了几个表数据后,发现某些表结构也不一样,很自然的想到了,中间的数据同步已经被丢掉了。

  我目前能快速做的,就是先主动把从库表结构更改为一致状态,以让后续数据同步能顺利进行。操作过程中,提示了很多错误,我完全忽略。但这在我最后的思考中,成了思路来源!

  我把结构变更操作后,数据总算恢复了平静,从库数据写入了。还不错,从这一刻起,数据是正常的。

  然而,这里遇到了另一个更大的问题:数据一致性!两个库的数据不一致!(这是业界最为重视的话题之一)!不过幸好,这只是个从库。但是有很多业务是从这个库数据数据源的,这绝逼会成为生产事故的啊。

  事情也不算太糟,虽然db小白很着急,db老鸟们却在笑:小场面,小场面!你不是主库的数据源是正确的嘛,同步过来就好了嘛!

  是的,只要从主库将数据搞一份过来就好了嘛!但是,怎么搞?

  和虽然听过很多的道理,却依旧过不好这一生一般。虽然你知道数据库的n种操作姿势,却不一定能在关键的时候用出一招!

    1. 一是最笨型姿势:直接将从库的数据删除,从主库里把全里数据导过来;即:备份&恢复!
    2. 导入的方式可以是自己dump,也可以利用dts进行全量初始化;
    3. 二还是笨的:根据数据表时间点,导出停顿时间段的数据,挨个导入到从库。这很危险,因为你可能导入一些过期的数据;
    4. 三使用dump数据导入:使用mysqldump 根据特征,取出数据,然后使用replace的方式,插入到从库中;注意一些表项的设置!

# --skip-add-locks 不使用锁进行表写入。因为使用锁时,极有可能导致更新花费很长时间!所以尽量将该参数带上!
# --skip-tz-utc 即不修改时区,数据库里存储多少就是多少。因为本身两个库的数据是相当的,所以无需修改该参数!
# -t 代表不创建表
mysqldump -uroot -t -p --skip-tz-utc --skip-add-locks  --replace --host=localhost -w "1" --databases test > lostdata.dump

    5. 使用dump时,参数设置最为关键,使用不当将导致数据取错,或者直接更新错误;

  四高级姿势:既然数据同步是通过binlog做的,那么,只要将binlog重新执行一遍,就好了嘛。但是风险同在,一是基于云的服务貌似不提供这种功能;二是binlog重读能保证结果一致吗(幂等性),还得研究研究!

不管怎么样,用笨人的方式,最终还是让数据保持一致了。

 mysqldump过程中,几点经验之谈:

  1. 所有表尽可能添加公共特征字段,比如 update_time,这样在同步的时候就可以方便使用where进行过滤了;
  2. 可以以mysqldump作为命令,执行定时更新数据的脚本;脚本如下:

#!/bin/bash
date_yesterday=`date '+%Y-%m-%d 00:00:00' -d '-1 day'`;
date_before_yesterday=`date '+%Y-%m-%d 00:00:00' -d '-2 day'`;
mysqldump -uroot -t -p --skip-tz-utc --skip-add-locks --replace --host=rm-xxx.mysql.rds.aliyuncs.com -w "update_time >= '$date_before_yesterday' AND update_time < '$date_yesterday'" --databases test --tables t_myusers > lastday.dump

sed '/^USE `.*`;/d' lastday.dump > lastday.dump
sed '/^CREATE DATABASE.*;/d' lastday.dump > lastday.dump

mysql -uroot -p123 -Dtest_new <  lastday.dump

  一句话总结:练为战!

上一篇:springcloud-05Eureka07-discovery服务发现


下一篇:【web层的增删改查以及分页查询 04】