由于一次上线操作的数据变更太多, 导致执行时间很长!
由于做手动主从关系, 所以操作落在了主库上.
由于主从关系不是对整个库的操作, 所以在有表新增的地方, 添加了 dts 新的同步关系.
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 时, 参数设置最为关键, 使用不当将导致数据取错, 或者直接更新错误;
6. 四高级姿势: 既然数据同步是通过 binlog 做的, 那么, 只要将 binlog 重新执行一遍, 就好了嘛. 但是风险同在, 一是基于云的服务貌似不提供这种功能; 二是 binlog 重读能保证结果一致吗 (幂等性), 还得研究研究!
mysqlbinlog --start-datetime="2018-08-09 00:00:00" --end-datetime='2018-08-11 00:00:00' /var/lib/MySQL/MySQL-bin.000001
这里可以指定特定的操作时间, 相当于场景重放. 风险自负!
不管怎么样, 用笨人的方式, 最终还是让数据保持一致了.
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
这样, 就可以 mysqldump 来做简单的备份, 以及不实时的数据同步了!(调整频率实现)
一句话总结: 练为战!
来源: https://www.cnblogs.com/yougewe/p/10459364.html