-------------------------------------------------------------------------------------正文------------------------------------------------------------------------------------
对待生产数据库上的操作要严肃,谨慎。
问题发生的具体情况:update tb1的脚本中, 有一条update语句没有where条件
问题造成的影响:tb1属于非业务核心表, 主要作用为信息存储,接近200W的数据全部被update
第一时间得知这个消息之后,首先确认这个表数据错误产生的影响,和业务人员沟通以后确认这个表相关的后续功能还没有开发完成,暂时没有业务查询;
然后考虑数据恢复的手段;
大方向来说,这种事故的处理方法主要有两个:1.从冷备/热备里面抽取这一张表的数据,然后还原到生产库,再由业务重新生成后续的数据;2.回滚掉这个update语句;
PS:另外的一个比较便利的办法,就是第一时间停掉延时从库的IO thread,然后从延时从库里面找到这张表,再视情况恢复数据,当然,前提是有延时从库;
方法1:很常规的方法,具体到实施的阶段,考虑了两种方式,
A.把生产库的tb1改名,然后从备份中导出tb1的数据插入到生产库;
B.从备份库上读出需要恢复的列数据,然后利用update批量改回去;
优缺点:
都要依靠备份数据进行恢复,光是通过备份文件重建库就会消耗不短的时间;
建库以后,方法A可以更快的恢复数据,但是进行大批量的数据插入的时候,有可能会产生单个长时间的事务,影响到主从同步;
方法B的思路类似于事务回滚,只不过是这个回滚的语句是根据备库的数据拼装起来的,恢复数据的时间相对于A要长很多;
这两个方法都有一个共通的问题,那就是从备份时间点到出问题的这一段时间,产生的数据都需要业务人员重新生成;
方法2:数据库的binlog处于ROW模式的时候,通过mysql的binlog解析工具, 可以解析出回滚语句,在库上面重新执行这些语句就可以了;
当数据库的规模达到一定程度的时候,重新建库会花费非常多的时间,在条件允许的情况下,利用binlog解析出回滚语句会是一种比较快捷的办法;
实际使用的办法:
实际采用的是方法1的B方式,相对来说耗时间比较长,采用这个方法的很重要的原因在于:这个表相关的后续功能还没有开发完成,暂时没有业务查询;
在这种大前提下,进行数据恢复的首要关注的指标:停/影响业务的时间不再和数据恢复时间相关,而是变成了进行数据恢复的时候不要影响到生产库;
当然也不能因为是圣诞节就扔这里不管跑掉了_(:з」∠)_;
所以采用方法1的B,重建备份库以后,用SQL语句组装了update语句,然后挂了一个后台脚本在跑,实际上花了很多时间;
如果这是业务相关的表的话,一个多小时基本上可以算是严重的生产事故了_(:з」∠)_(万幸是个暂时不怎么用的表)
为什么不用其他的方法:
方法1的A:可能会产生单个长时间的事务,影响主从同步;
方法2:这个库部署在XX云平台上,虽然binlog使用ROW格式的,但是看不到数据库服务器,碰不到binlog,只能放弃;
对待生产数据库上的操作要严肃,谨慎。
问题发生的具体情况:update tb1的脚本中, 有一条update语句没有where条件
问题造成的影响:tb1属于非业务核心表, 主要作用为信息存储,接近200W的数据全部被update
第一时间得知这个消息之后,首先确认这个表数据错误产生的影响,和业务人员沟通以后确认这个表相关的后续功能还没有开发完成,暂时没有业务查询;
然后考虑数据恢复的手段;
大方向来说,这种事故的处理方法主要有两个:1.从冷备/热备里面抽取这一张表的数据,然后还原到生产库,再由业务重新生成后续的数据;2.回滚掉这个update语句;
PS:另外的一个比较便利的办法,就是第一时间停掉延时从库的IO thread,然后从延时从库里面找到这张表,再视情况恢复数据,当然,前提是有延时从库;
方法1:很常规的方法,具体到实施的阶段,考虑了两种方式,
A.把生产库的tb1改名,然后从备份中导出tb1的数据插入到生产库;
B.从备份库上读出需要恢复的列数据,然后利用update批量改回去;
优缺点:
都要依靠备份数据进行恢复,光是通过备份文件重建库就会消耗不短的时间;
建库以后,方法A可以更快的恢复数据,但是进行大批量的数据插入的时候,有可能会产生单个长时间的事务,影响到主从同步;
方法B的思路类似于事务回滚,只不过是这个回滚的语句是根据备库的数据拼装起来的,恢复数据的时间相对于A要长很多;
这两个方法都有一个共通的问题,那就是从备份时间点到出问题的这一段时间,产生的数据都需要业务人员重新生成;
方法2:数据库的binlog处于ROW模式的时候,通过mysql的binlog解析工具, 可以解析出回滚语句,在库上面重新执行这些语句就可以了;
当数据库的规模达到一定程度的时候,重新建库会花费非常多的时间,在条件允许的情况下,利用binlog解析出回滚语句会是一种比较快捷的办法;
实际使用的办法:
实际采用的是方法1的B方式,相对来说耗时间比较长,采用这个方法的很重要的原因在于:这个表相关的后续功能还没有开发完成,暂时没有业务查询;
在这种大前提下,进行数据恢复的首要关注的指标:停/影响业务的时间不再和数据恢复时间相关,而是变成了进行数据恢复的时候不要影响到生产库;
当然也不能因为是圣诞节就扔这里不管跑掉了_(:з」∠)_;
所以采用方法1的B,重建备份库以后,用SQL语句组装了update语句,然后挂了一个后台脚本在跑,实际上花了很多时间;
如果这是业务相关的表的话,一个多小时基本上可以算是严重的生产事故了_(:з」∠)_(万幸是个暂时不怎么用的表)
为什么不用其他的方法:
方法1的A:可能会产生单个长时间的事务,影响主从同步;
方法2:这个库部署在XX云平台上,虽然binlog使用ROW格式的,但是看不到数据库服务器,碰不到binlog,只能放弃;