中文站

删库不跑路!数据库误删有几种恢复方式?

不得不说,在使用数据库的过程中,不管是业务开发者还是运维人员,都有可能对数据库进行误操作,运维人员对数据库有最大的操作权限,可以进行schema级别的操作,容易发生误删库或删表等错误的DDL操作。开发人员一般没有这么大的操作权限,但是同样能够造成灾难级的误操作,比如全表不带条件的update或delete等。

近期出现的几个线上库误操作,导致DBA着实忙碌了一阵,心有戚戚焉。虽然误操作有时候看起来防不胜防,但是办法总比问题多。下面简单聊聊误删除发生后,有哪些高效的补救措施。

第一种是延迟从库。在MySQL中,该功能从5.6开始支持,在此举5.7为例。

在建立延迟库复制关系时,除了复制有指定时间延迟外,其他跟普通从库相同。发现误删除后,可以停止从库复制,找到误删除发生的位置后,重启复制并指定要复制到的gtid或binlog位置。这样能精确恢复到出错前的位置。

接下来的办法很多,如果是表误删,可以使用延迟从库上的对应表来重建主库上的表数据。如果是全表update,可以使用从库上的表覆盖掉主库上的。

若要把延迟从库提升为主,则可通过配置filter来过滤掉误删除的时间区间内该表对应的binlog event,完成过滤复制后,再恢复成正常的复制关系完成数据复制。最后将其切换成主库即可。

当然,也可以使用mysqlbinlog工具来做上述的事情。延迟从库复制停掉后,可以使用mysqlbinlog精确回放到指定位置的binlog,mysqlbinlog支持表级的binlog event过滤。

在网易的MySQL分支中,mysqlbinlog支持过滤/指定某种类型的event,比如仅输出某库某表的update类型binlog event。

由于延迟从库平时不会有用户访问,所以其资源和规格可以尽可能降低。数据存储可以使用高压缩的存储引擎,比如MyRocks来。这样可以极大节省延迟从库的成本开销。

第二种是binlog增量备份,每个版本的MySQL都可以做,但是在基于gtid的复制上更容易做,在5.5版本上,要实现连续不间断的binlog复制是有难度的,需要处理主从切换等多种场景,因为主从切换后,binlog文件的索引和偏移位置都发生变化,需要找到主从库的binlog对应关系,而且5.5版本的从库一般没有开启binlog,这些都是难点。但对于基于gtid的复制,主从切换后,只需要从上次备份结束的事务gtid对应的binlog位置开始即可。相比基于文件偏移的增量备份,简单很多。

在进行恢复时,基于增量备份的误删除可以先恢复出一个误删除前的全量备份,再通过mysqlbinlog回放binlog到误删除位置,方法类似于第一种的mysqlbinlog使用方式。

第三种是flashback方案。这其实是成本最低的一种方法,又可以分为2种,ddl的flashback和dml的flashback。

其中ddl可通过将drop或truncate等变为rename来做,目前业界有些MySQL分支已经实现,InnoSQL 5.5版本开始支持基于binlog event的ddl flashback方式,最早由阿里云丁奇实现,但由于MySQL的ddl实现方案不断改进,原方式使用范围越来越小,另外,由于引入新的binlog event类型,会导致跟其他版本复制不兼容。目前正在实现无需binlog event参与的ddl flashback方式。

其实现方式类似于回收站,将rename的表重新rename回来。该方法的不足时容易引起磁盘空间占用过多,这可以通过过期清理回收站里的表来解决。

对于dml,可以将insert改为delete,delete改为insert,update对换前后项的方式进行。相应的工具有好几种,包括最经典的flashback,该功能最早由阿里云彭立勋实现,InnoSQL 5.5版本移植了源代码,并进行了针对性的优化和增强。一般情况下,发生误删除到发现,时间比较短,所以flashback所需的binlog是在的。这种方式的不足时需要binlog是row格式的,而且得保留完整的dml前后项,不过主流的MySQL数据库配置均支持。

一般线上库误删除的恢复都是DBA来做的。作为数据库内核维护者,仅提供相应的工具和恢复方案,从内核层面提供更加高效的方案和工具,是我们的责任。

文章来源:网易云  作者:网易数据库团队