wtf!rds数据同步居然出问题了--菜鸟db的数据修复历程
由于一次上线操作的数据变更太多,导致执行时间很长!
由于做手动主从关系,所以操作落在了主库上。
由于主从关系不是对整个库的操作,所以在有表新增的地方,添加了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 "" --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.
这里可以指定特定的操作时间,相当于场景重放。风险自负!
不管怎么样,用笨人的方式,最终还是让数据保持一致了。
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来做简单的备份,以及不实时的数据同步了!(调整频率实现)
完整优化的脚本参考如下:
#!/bin/bash # common configs
tmp_dump_file_path="/tmp/test-tmp.dump";
profile_dump_options=" --skip-tz-utc --single-transaction --replace -t -c"; # --skip-opt # data source origin configs
from_host="172.1.1.123";
from_username="root";
from_password='';
from_database="test_from";
from_database_tables="t_test_from1 t_from_tab2" # data sync target configs
to_host="test1.mysql.rds.aliyuncs.com";
to_username="test_dfrom"; # test_dto
to_password='';
to_database='test'; # test, test crawler, for debug
to_database_tables='t_test_to t_tab_to2'; # update where condition settings...
#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 -1 minute'`;
date_yesterday=`date '+%Y-%m-%d %H:%M:%S' -d '-1 hour'`; # test frequency
date_before_yesterday=`date '+%Y-%m-%d %H:%M:%S' -d '-2 hour -1 minute'`;
dump_condition_where="update_time >= '$date_before_yesterday' AND update_time < '$date_yesterday'" echo "/usr/bin/mysqldump -u"${from_username}" -p"${from_password}" ${profile_dump_options} -h${from_host} -w "${dump_condition_where}" --databases ${from_database} --tables ${from_database_tables} > ${tmp_dump_file_path}";
/usr/bin/mysqldump -u"${from_username}" -p"${from_password}" ${profile_dump_options} -h${from_host} -w "${dump_condition_where}" --databases ${from_database} --tables ${from_database_tables} > ${tmp_dump_file_path};
#/usr/bin/mysqldump --defaults-extra-file=/etc/my.cnf -w "" --databases ${from_database} --tables t_role2 > ${tmp_dump_file_path}; # for elastic sync options
sed -i '/^USE `.*`;/d' ${tmp_dump_file_path}
sed -i '/^CREATE DATABASE.*;/d' ${tmp_dump_file_path}
sed -i '/^SET .*/d' ${tmp_dump_file_path}
sed -i "/^\([0-9a-z:-]\+\)[,'\";]\+/d" ${tmp_dump_file_path}
search_str_arr=(${from_database_tables});
replace_str_arr=(${to_database_tables});
for((i=; i<${#replace_str_arr[*]}; i++))
do
echo "sed -i "s/\`${search_str_arr[$i]}\`/\`${replace_str_arr[$i]}\`/g" ${tmp_dump_file_path};"
sed -i "s/\`${search_str_arr[$i]}\`/\`${replace_str_arr[$i]}\`/g" ${tmp_dump_file_path};
done; echo "mysql -u"${to_username}" -p"${to_password}" --host=${to_host} -D"${to_database}" < ${tmp_dump_file_path}"; # for debug
/usr/bin/mysql -u"${to_username}" -p"${to_password}" --host=${to_host} -D"${to_database}" < ${tmp_dump_file_path} # for debug
echo "cat ${tmp_dump_file_path}";
tail -n ${tmp_dump_file_path} | head -n ;
一句话总结:练为战!
wtf!rds数据同步居然出问题了--菜鸟db的数据修复历程的更多相关文章
- volatile并不能保证数据同步、只能保证读取到最新主内存数据
在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配.其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈, 线程栈保存了线程运行时候变量值信息.当线程访问某一个对象时候值的 ...
- 线程安全、数据同步之 synchronized 与 Lock
本文Demo下载传送门 写在前面 本篇文章讲的东西都是Android开源网络框架NoHttp的核心点,当然线程.多线程.数据安全这是Java中就有的,为了运行快我们用一个Java项目来讲解. 为什么要 ...
- MongoDB副本集配置系列十一:MongoDB 数据同步原理和自动故障转移的原理
1:数据同步的原理: 当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步: 1:检查自己local库的oplog.rs集合找出最近的时间戳. 2:检查Primary ...
- MongoDB副本集配置系列十:MongoDB local库详解和数据同步原理
1:local库是MongoDB的系统库,记录着时间戳和索引和复制集等信息 gechongrepl:PRIMARY> use local switched to db local gechong ...
- 总结:基于Oracle Logminer数据同步
第 1 页 共 20 页 出自石山园主,博客地址:http://www.cnblogs.com/shishanyuan LogMiner 配置使用手册 1 Logminer 简介 1.1 LogMin ...
- 基于 MySQL Binlog 的 Elasticsearch 数据同步实践 原
一.背景 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品.订单等数据的多维度检索. 使用 Elasticsearch 存储业务数据可以 ...
- 基于MySQL Binlog的Elasticsearch数据同步实践
一.为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品.订单等数据的多维度检索. 使用 Elasticsearch 存储业务数 ...
- 搞懂 ZooKeeper 集群的数据同步
本文作者:HelloGitHub-老荀 Hi,这里是 HelloGitHub 推出的 HelloZooKeeper 系列,免费开源.有趣.入门级的 ZooKeeper 教程,面向有编程基础的新手. 项 ...
- Oracle和Elasticsearch数据同步
Python编写Oracle和Elasticsearch数据同步脚本 标签: elasticsearchoraclecx_Oraclepython数据同步 Python知识库 一.版本 Pyth ...
随机推荐
- dva/docs/GettingStarted.md
进入目录安装依赖: npm i 或者 yarn install开发: npm run dev npm install 太慢,试试yarn吧.建议用npm install yarn -g进行安装. Co ...
- IP地址和MAC地址的关系
IP地址是网络层的概念,而MAC地址是数据链路层的概念.IP地址在网络层上对不同的硬件地址类型进行了统一,从而提供网络互联的可能:而硬件地址在真正的数据传输中要用到.当应用程序把数据从源主机发送到目标 ...
- 富文本编辑器UEditor自定义工具栏(三、自定义工具栏功能按钮图标及工具栏样式简单修改)
导读 富文本编辑器UEditor提供丰富了定制配置项,如果想设置个性化的工具栏按钮图标有无办法呢?答案是肯定的!前两篇博文简要介绍了通过将原工具栏隐藏,在自定义的外部按钮上,调用UEditor各命令实 ...
- Collection集合详解
/*Collection--List:元素是有序的,元素可以重复.因为该集合体系有索引. ---ArrayList;底层的数据结构使用的是数组结构.特点:查询速度很快.但是增删很慢.线程不同步 --- ...
- 你不知道的JavaScript--Item4 基本类型和基本包装类型(引用类型)
1.基本类型和引用类型 基本的数据类型有5个:undefined,boolean,number,string,null typeof null; //"object" typeof ...
- HTML5 CSS3 经典案例:无插件拖拽上传图片 (支持预览与批量) (二)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/31513065 上一篇已经实现了这个项目的整体的HTML和CSS: HTML5 C ...
- 关于Google 圆角 高光 高宽 自适应 按钮
最近看了张鑫旭老师关于Google搜索按钮的博客,感觉启示颇多.下面我就详说一下这个按钮的代码,由于W3C新版本的更新,之前的代码会有部分累赘, 在此,我做了些修改.当然,想观摩原版的可以,狠狠的戳链 ...
- 【转】用信鸽来解释 HTTPS
一.引文出处 注:分享交流技术.本文摘自开源中国翻译,翻译者:JonnHuang,句号句号 译文原网址:https://www.oschina.net/translate/https-explaine ...
- Hibernate 操作数据库
com.tao.pojo实体类 package com.tao.pojo; public class User { private int id; private String name; priva ...
- BZOJ_2882_工艺_后缀数组
BZOJ_2882_工艺_后缀数组 Description 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且 ...