误删数据后的处理

误删数据的几种情况

对于误删除数据进行了简单的分类:

  1. 使用delete语句误删除数据航;
  2. 使用droptable或者truncate table误删除表数据;
  3. 使用dropdatabase语句误删除数据库;
  4. 使用rm命令删除整个mysql实例;

误删行–用delete

  • 方法:可使用工具Flashback来恢复误删除的数据;
  • 条件:使用FalshBack的条件,binlog_format=row和 binlog_row_image=FULL
  • 原理:解析binlog,并且把binlog的逆向修改,那会原数据库重放;
  • 注意:
    • 逆向后不要重新那回主库重放,要先从一个林水库开始,然后由临时库在恢复到主库上,防止直接在一个在线的主库上还原,破坏了数据关联,造成数据2次破坏;
    • 数据库的防范于未然:sql语句的安全模式:set [global] sql_safe_updates = 1,这样当update delete没有where条件时候就会报错;

drop table或者truncate table

delete删除全表往往性能会很差,因为要写undolog redolog binlog等,这时候如果有删除全表的需求就可以考虑用:drop table或者truncate table来删除

当使用这几个命令时候我们的binlog是statement格式的,所以也没法用上面的方法恢复数据。

误删库表恢复的流程是怎样的呢?

  1. 去最后一次全量备份的库,恢复出一个临时库;
  2. 在日志备份里,取当前备份点之后的日志,除了误删除的语句,应用到临时库中;

如图:
avator

注意:

  1. 如果临时库的实例上有多个数据库,在使用mysqlbinlog命令可以加上–database参数,来指定误删除库;
  2. 恢复数据跳过误删除的binlog的方法上:
    1. 如果原实例没有GTID模式:我们只能在备份日志中先找到误删除的那个操作用-stop-position参数执行前的日志,在用-start-position从误删除之后的操作执行;
    2. GTID模式:我们可以在临时库上执行:set gtid_next=gtid1;begin;commit;先把这个gtid加到临时库的gtidset中,之后重放binlog会自动跳过这个操作

恢复表和库的加速

上面的做法还是不够快,因为:

  1. 如果是误删表:我们期望只恢复这张表的数据,但是mysqlbinlog工具不能只解析一张表的日志;
  2. 用mysqlbinlog恢复出的应用日志,只能是单线程恢复,无法利用并行复制的功能;

解决方案:

第一种方法:临时库在被全量恢复(设置了gtid后)后,将这个临时库置为主库的从库,然后这个临时库在执行start salve之前执行;

1
2
#让临时库只同步误删除的表,同时主->备可以利用并行复制
change replication filter replicate_do_table = (tbl_name)

如图:
avator

mysql的binlog丢失

有一种情况,如果要恢复的是个很久远的库,备库上又不能无限制的保存binlog,导致需要的binlog备库没有log的情况该如何操作呢?

  1. 假设临时库上需要的master.000005,而备库上从master.000007开始的,意味这我们要从备份系统上下载master.000005,master.000006放到备库上
  2. 之后打开备库的master.index文件上(根据配置名字可能不同),加上”./master.000005”,”./master.000006”
  3. 重启备库,让备库识别这俩个文件
  4. 建立主备关系开始同步数据

综上:误删库的恢复是通过定期全量备份+增量备份来恢复数据库,建议DBA把流程做成自动化,同时定期演练减伤损失。

搭建延迟复制备库

假设:当一个大库的备份周期是1周一备份,同时在第6天发生了误操作,这时候就要恢复6天的binlog,恢复时间可能是按天计的,对于在线业务是不允许的。这时候我们可以通过搭建一个延迟赋值的备库来解决。

  1. 这个机制是mysql5.6之后引入的有一个机制,我们在备库可以通过命令CHANGE MASTER TO MASTER_DELAY=N(单位:秒),即延迟N秒同步命令。
  2. 比如:CHANGE MASTER TO MASTER_DELAY=3600,那么当一个误操作发生后,这个备库会在一个小时以后收到这条命令,我们可以在这段时间内stop salve;
  3. 然后恢复这一个小时的数据并且跳过这个命令即可;

预防误删除库/表的方法

我们应该尽量最大化的目标误删除操作:

  1. 账号分离:

    1. 业务账号应该只有MDL权限
    2. 日常的数据查询值用只读账号
  2. 指定操作规范:

    1. 删除表前线对表改名,观察一段时间
    2. 该表明要有命名规范比如_to_be_deleted

rm删除

HA会选取一个从库作为主库,我们只需要回复这个机器即可;
为防止这个事情发生可以做跨机房或者跨城市备份