案例 - 误删千万的表
某天下午,正在给测试库录入数据,看到有截断的warnings,就把表delete掉,重新导入,在做这个导入操作的同时,还在线上给业务做一个update数据的操作,突然之间,误把测试库的secureCRT当做测试的窗口,进行了一个delete操作,2秒后还没删除成功,再看一下表名字,原来是线上业务的表,当场懵逼了
马上ctrl + c 取消delete语句,但因为用的是myshard中间件,索引 ctrl + v 没用有,delete的语句,再就传递到下面挂在的mysql里执行,于是2000万的表就这样被删除了,全球一共9个节点,也因为同步dml sql,而导致所有节点的该表被删除
不过myshard的有一个保护机制,就是每行数据都会加入一个__deleted字段,myshard的delete数据,相当于mysql层面的 update deleted = 1 而已,3天之后,才会真正把数据删掉,目的是防止人为误操作
于是我选择业务使用最多的其中一个节点,进入mysql层面,SET sql_log_bin = 0 ,然后进行
update 表 set deleted=0 where deleted=1
恢复一个节点需要5分钟,把第一个节点恢复以后,马上通知业务,把全球使用改表的业务,都切到已经恢复的那个节点,其他节点先不要使用,于是逐步恢复其他节点,最后一共消耗20分钟把数据恢复回来
当然这5分钟期间,虽然所有节点的这个表都是没有数据,但不一定查询不到数据,因为有redis在扛着,redis的命中率有95%,只有在redis上查询不到数据,接着往DB上查询,才会出现取不到数据的情况
当时以为这样就完事了,于是去开会,开会回来后,业务说数据库的同步有问题,数据不一致了......
与内核开发的同事调查,发现进行误操作的那个节点的数据,不能顺利同步到其他节点,原因2千万的表,delete语句一下去,就生成了18G的binlog,而myshard的sync同步进程,识别不了超过4G以上的binlog文件,把位置点变成一个负数,而负数位置点的监控是我们监控脚本没有覆盖到的
-rw-rw----. 1 mysql mysql 101M May 31 16:33 mysql-bin.270756 -rw-rw----. 1 mysql mysql 18G May 31 16:38 mysql-bin.270757 -rw-rw----. 1 mysql mysql 101M May 31 16:38 mysql-bin.270758
做法是跳过那个18G的binlog,直接去连下一个binlog,先恢复同步,同步落后了20G,等同步追完以后,大概造成了4个小时的数据延迟,充值延迟导致
这个mysql-bin.270757的二进制日志,用了5分钟生成,其实当时还可以做一个补救措施,就是进入myshard下面的MySQL层面,直接把唯一一条delete语句kill掉,那就可以减少binlog的大小,以及数据的生成时间,不过当时太急没有反应过来
18G的binlog,99%是那条delete SQL生成的row模式的数据文件,但期间还有其他业务正常的SQL,于是使用了大众点评的binlog2sql恢复工作,目的是把二进制文件,解析成具体的SQL语句
使用mysqlbinlog去解析也可以,只不过看不到具体的SQL语句,但业务是需要看到具体的SQL,才能进行恢复,因为比如一些update a = a + 100 类似充值的语句,就不能直接更新了,它是依赖过去的值,如果过去的值都不准确(数据延迟),那么更新回去会出问题的,这样要让业务去衡量怎么处理,所以得把具体的SQL语句提取出来
https://github.com/danfengcao/binlog2sql
其实阿里也有一个binlog解析工具,只不过阿里最后输出的结果是反向解析,比如delete的语句,阿里的工具会生成insert,我的场景只需要提取正常的sql即可,不需要反向解析,于是没有采用
但不管是大众点评,还是阿里的工具,都需要在线去连接数据库的,目的是为了获取information_schema.columns表,去获取表的字段名字,再替换到binlog解析后的@1,@2,@3字段,但我并不想在online的DB上去解析这个18G的binlog,担心消耗cpu资源,我把这个18G的binlog拷贝一个测试库上
想了很久才想到一个方法,就是把测试库,伪装成online的数据库,把测试库的schema都删掉,然后把当前的binlog名字,替换成18G的binlog名字,觉得脑洞有点大,但工具能用了,当时写的脚本关键部分是这样子的
able_array=( 表1 表2 表3 ....... 数据库上所有的表名 ) for table_name in "${table_array[@]}";do python binlog2sql.py -h127.0.0.1 -P端口 -u账号 -p密码 -d数据库 --start-file='18G的binlog文件' -t${table_name} > /data1/flashback/"${table_name}".sql done
于是就把18G的sql都解析出来了,比如像这样的格式,有SQL语句,有时间,每条SQL语句占用1行,于是就通知业务,再继续做恢复的事情
INSERT INTO `myshard`.`xxxxxxxxx`(`status`, `actor_uid`, `style`, `ctime`, `__deleted`, `__version`, `sid`, `date`, `utime`, `type`, `uid`) VALUES (0, xxxxxxxxx, 0, 1496219633, 0, xxxxxxxxx, xxxxxxxxx, 20170531, 1496219633, 1, 1605227422); #start 106192 end 106420 time 2017-05-31 16:33:53 INSERT INTO `myshard`.`xxxxxxxxx`(`status`, `actor_uid`, `style`, `ctime`, `__deleted`, `__version`, `sid`, `date`, `utime`, `type`, `uid`) VALUES (0, xxxxxxxxx, 0, 1496219633, 0, xxxxxxxxx, xxxxxxxxx, 20170531, 1496219633, 3, 1573543992); #start 258936 end 259164 time 2017-05-31 16:33:53 INSERT INTO `myshard`.`xxxxxxxxx`(`status`, `actor_uid`, `style`, `ctime`, `__deleted`, `__version`, `sid`, `date`, `utime`, `type`, `uid`) VALUES (0, xxxxxxxxx, 0, 1496219634, 0, xxxxxxxxx, xxxxxxxxx, 20170531, 1496219634, 3, 1509357246); #start 473268 end 473496 time 2017-05-31 16:33:54 INSERT INTO `myshard`.`xxxxxxxxx`(`status`, `actor_uid`, `style`, `ctime`, `__deleted`, `__version`, `sid`, `date`, `utime`, `type`, `uid`) VALUES (0, xxxxxxxxx, 0, 1496219636, 0, xxxxxxxxx, xxxxxxxxx, 20170531, 1496219636, 1, 1610811581); #start 1114346 end 1114574 time 2017-05-31 16:33:56 INSERT INTO `myshard`.`xxxxxxxxx`(`status`, `actor_uid`, `style`, `ctime`, `__deleted`, `__version`, `sid`, `date`, `utime`, `type`, `uid`) VALUES (0, xxxxxxxxx, 0, 1496219636, 0, xxxxxxxxx, xxxxxxxxx, 20170531, 1496219636, 1, 1593006833); #start 1295075 end 1295303 time 2017-05-31 16:33:56
本次最大的教训是,在执行 delete ,rm ,rsync ,mv ,update的操作之前,要确认好ip,实例,心里要默念个5秒再执行操作,小心谨慎

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
vSphere 6.5密码正确不能登录解决方法
今天新安装了一个VMware ESXi 6.5的系统,密码仍然用的习惯采用的密码。但在使用中,无论是使用vSphere Client连接,还是在vCenter Server中添加这台ESXi系统,都是提示密码不对,最后重置系统设置(密码清空),通过在vSphere Client设置新的密码的方法解决。下面简单回顾一下问题的现象及解决过程。 (1)使用vSphere Client登录新安装的ESXi 6.5,提示密码不对,如图1-1所示。 (2)使用VMware Host Client登录,仍然提示密码不对。如图1-2所示。 图1-1 提示密码不正确 图1-2 提示密码不对 (3)在控制台前登录,密码是正确的。因为这台是新安装的,当前也没有进行其他配置。进入控制台,选择"Reset System Configuration"重置系统配置,在弹出的对话框中按F11键,如图1-3所示。重置系统之后,ESXi重新启动。 图1-3 重置系统 (4)再次进入系统之后,使用空密码登录,在"Configure Management Network→IPv4 Configuration"重新设置管理地址...
- 下一篇
线上服务mcelog负载异常分析处理流程
一、问题概述: Nginx服务器,HP,有冗余,其中一台服务器mcelog负载比较高,日志秒级别,已经影响了此服务器业务。 tail -f /var/log/mcelog #注意看此信息是不断循环,注意看 Transaction:Memoryscrubbingerror MemCtrl:Correctedpatrolscruberror Erroroverflow Correctederror #注意看其它信息 CPU16BANK9 MCE11 337335MCi_MISCregistervalid 337336MCi_ADDRregistervalid 337337MCA:MEMORYCONTROLLERMS_CHANNEL1_ERR 337338Transaction:Memoryscrubbingerror 337339MemCtrl:Correctedpatrolscruberror 337340 337341STATUScc0048c0000800c1MCGSTATUS0 337342MCGCAP1000812APICID8SOCKETID0 337343CPUIDVendo...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Mario游戏-低调大师作品
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- 2048小游戏-低调大师作品
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Linux系统CentOS6、CentOS7手动修改IP地址
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16