惊险!记一次从删库到恢复的经历

公司以前在作东南亚社交项目,涉及到的各个端人员比较多,开发、运维、产品、测试20多个,固然,对大公司来讲,20其实不算多,进入正题,咱们数据库使用的是MySQL,运维搭建的主从,而正是因为这个所谓的主从,害苦了开发的兄弟们;缓存使用的是Redis,MySQL数据同步到Redis使用的是阿里开源的Canal,了解Canal的都知道,Canal是读取MySQL的二进制文件,进而获得数据的变动,而后同步到Redis。mysql

某天傍晚,后台开发兄弟们平常更新,因为产品要求用户的昵称支持输入表情,咱们不得不修改MySQL的配置文件,使其支持表情,修改了Master配置文件,天然就须要修改Slave 的配置文件,将Master重启后,而后重启Slave,都重启后,发现master上的数据不能同步到slave了,我擦,不过因为项目刚刚起步,访问量不大,加上天色已晚,后台开发兄弟决定,不能同步就不能同步吧,明天找运维同事搞定。sql

次日,运维同事了解状况后,连上服务器,一顿操做。下午三点左右, 产品正在演示APP,说APP首页没有数据了,咱们说,呵呵,怎么可能,而后登上数据库后,我我我擦,master 用户表的数据被清空了,瞬间有点发毛,难道被攻击了,赶忙看下 slave,我*,比master上的数据都干净,而此时的master 里面的用户表 还有几条刚刚注册进来的几条数据,冷汗直流。缓存,对,看下缓存中,赶忙连上缓存服务器,疑问了,缓存里面 还有数据,master 用户表的数据没有了,而缓存又是读取的master里面的二进制文件,先不考虑这个问题,目前的紧急问题是赶忙恢复数据。因为开启了binlog,那就从这里恢复,一同事赶忙下载binlog,玛德,文件太大,拉下来 将近40分钟,这个方法暂缓。诶,缓存不是有数据嘛,那就把缓存里面的数据从新写到MySQL,赶忙写一个for循环,从 丢失的数据的 ID 往前读,而后一个个insert到数据库,固然,这种方法会致使数据有点旧,不过,和数据彻底丢失比起来,那就毛毛雨了。终于,历经将近一小时,数据恢复。数据库

数据恢复后,咱们首要的目标就是查缘由,缘由无非就是两个,一是被攻击,二是内部人员所为。查看MySQL的二进制日志,数据丢失大约是在3点左右,而服务器是在曼谷,时间比北京时间晚一个小时,也就是服务器上的时间是2点左右,拉二进制文件找缘由,呵,太慢了,几行命令搞定,缓存

-- 查看某个时间段的二进制日志,而且输出到指定的文件
mysqlbinlog --no-defaults --start-datetime="2018-12-12 13:00:00" --stop-datetime="2018-12-12 14:40:00" mysql-bin.000085 -vv --base64-output=decode-rows | more  >> target.txt

-- 将@一、@2等一系列看不懂的符号转换为SQL语句
cat target.txt | sed -n '/###/p' | sed 's/### //g;s/\/\*.*/,/g;s/DELETE FROM/INSERT INTO/g;' | sed -r 's/(@4.*),/\1;/g' | sed 's/@[0-9]*\=//g' > test.sql
复制代码

而后将 test.sql 文件拉下来,查看,发现两处可疑点(即两条SQL),以下:服务器

-- 建立一个像user同样的表,user_bak
create table user_bak like user;
-- 删除 user_bak
drop table user_bak;
复制代码

可是,没有清空或者删除user 表的sql,奇了怪了。忽然,技术总监过来问,有没有找到缘由,我说尚未,只是找到了两条可疑的SQL,可是还没发现有清空user的SQL,由于一直在看master上的日志,由于是主从,看master 上的日志和看slave上的同样,然而,总监却说,slave上的日志也要查下,好吧,虽然以为看了没什么用,谁让他是老大呢。登上slave服务器,却发现,为何 slave 上也有二进制日志呢,先无论,看下日志,发现有以下SQL:运维

-- 删除 user
drop table user;
-- 建立user
create table user(
	...省略字段
)
COMMENT='用户表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=4xxxxxx
;
复制代码

虽然打脸了,可是为何slave上也会有二进制日志呢,赶忙找运维问下究竟是不是主从,运维说是,算了,仍是看下配置文件,呵呵,居然是主主,不是说好的主从呢,怪不得在 slave上执行了 删除用户表,而后建立用户表,建立的下一个自增点仍是丢失前的自增点,master上用户表的数据就不存在了,这样Redis中数据存在的缘由也破解了,Redis 读取的是master中的二进制文件,正是因为从所谓的“从”删除而后重建user表后(记录到“从”的二进制日志),“主”上就有了user 表(记录到“主”的中继日志,并无在这个“主”的二进制日志,因此 Canal根本没有读取到在“从”上的操做),缘由是找到了,可是 是谁执行的呢??当咱们正在讨论的时候,运维说他在作测试,测试昨天的主从有没有正常了,他在修复昨天不能主从复制的问题。测试

崩溃,修复就修复,执行删除干吗,而说好的主从,咋还变成主主了,问题 缘由找到了,意味着不用加班到天亮了。spa

这种问题必定要杜绝:日志

  • 非特殊状况,禁止使用ROOT帐户;
  • 相关人员分配MySQL帐户,制定权限;
  • 禁止执行不带条件的DELETE、UPDATE,TRUNCATE,DROP

欢迎关注个人公众号,第一时间接收最新文章~ 搜索公众号: 码咖 或者 扫描下方二维码:

img
相关文章
相关标签/搜索