数据误删的操作分为以下几类:

  1. 使用delete语句误删除数据行
  2. 使用drop table或者truncate table语句误删除数据表。
  3. 使用drop database语句误删除数据库。
  4. 使用rm命令误删除整个mysql实例。

误删行

使用delete语句误删行,使用Flashback工具闪回把数据恢复过来。

其执行原理就是修改binlog的内容,拿回原库重放。需要确保 binlog_format=row 和 binlog_row_image=FULL。记录更新前后的数据状态。

修改binlog的内容,并按照其反向顺序放回原库执行:

  • delete变为insert
  • insert变为delete
  • update将操作前后的数据调换位置

不过对于 truncate /drop table 和 drop database 命令删除的数据,就没办法通过 Flashback 来恢复了。因为这三条命令只会使用statement格式记录binlog,自然无法从binlog中进行恢复。

误删库表

这种情况下要恢复数据,就要使用全量备份+增量日志的方式了,这个方案要求线上有定期的全量备份,并且实时备份binlog。

在这两个条件都具备的情况下,假如有人中午 12 点误删了一个库,恢复数据的流程如下:

  1. 取最近一次全量备份,假设这个库是一天一备,上次备份是当天 0 点;
  2. 用备份恢复出一个临时库;
  3. 从日志备份里面,取出凌晨 0 点之后的日志;
  4. 把这些日志,除了误删除数据的语句外,全部应用到临时库。

为了加速恢复,可以在使用mysqlbinlog的时候带上–database 参数,用来指定误删表所在的库。 至于跳过误删的操作,使用—start-position在此操作前停止,然后使用—start-position在其之后继续开始。如果开启了GTID模式,那么就更简单了,将对应GTID加入就会自动跳过了。

延迟复制备库

对于数据量非常大,但是又是核心的数据库,要求恢复的时间不会太长,就可以使用搭建延迟复制的备库。

使用CHANGE MASTER TO MASTER_DELAY = N 命令,可以指定这个备库持续保持跟主库有 N 秒的延迟。比如N为1个小时,只要在这一个小时内发现了误操作的命令,这个命令就还没有在备库上执行,然后备库stop slave,通过前面的方法,跳过误操作的命令,就可以恢复数据。

恢复数据最多不会花费超过N秒。

预防

再精妙的误操作恢复方法都不如不会误操作。

首先便是账号分离,只有必要更新的时候才使用更新操作。

指定规范操作。删除表之前必须先改命,一段时间内对业务没有影响再删除。

rm删除数据

只要不是恶意删除整个集群,HA就会工作选出新的主库继续工作,只要把节点的数据恢复之后再接入集群就好。