误删数据也是难免会发生的事(对于粗心的我来说),接下来根据血泪经验讲一下如何恢复被误删的数据。

首先你要对mysql有配置binlog

具体的配置方式网上有很多,我就不写了,下面附上我的配置。

binlog_format = ROW
log-bin = /data/arch/mysql-bin
log_bin_index = /data/arch/mysql-bin.index
expire_logs_days = 7

注意⚠️,这边的binlog_format必须设置为Row Level或者Mixed,
不然是不会记录delete的具体语句的,也就没法恢复了。
参考:
Mysql binlog 三种模式的区别

接下来开始作数据恢复

分为三步:

  1. 将对应表的delete语句全部拷出来
  2. 进行字符转换,转成可执行的insert sql语句。
  3. 执行sql语句,恢复成功。

第一步,导出binlog

./mysqlbinlog --no-defaults --base64-output=decode-rows -vv  /data/arch/mysql-bin.000237| sed -n '/### DELETE FROM `safept`.`accident`/,/COMMIT/p'> /root/delete.txt

选择binlog的分片,执行对应表sql的筛选,导出。

第二步,正则转换

首先这边是参考了:

通过binlog恢复误delete的数据(一)

我这边对其中的每一个步骤都添加了解释说明,方便不了解sed和正则的朋友可以快速理解这些脚本的含义:

sed -n '/^###/'p delete2.txt >b.txt

-n:显示scrpit处理后的结果

p:打印,通常 p 会与参数 sed -n 一起运行

保留以###开始的行数据。

mysql binlog恢复 mysql binlog恢复删除的表数据_sed

sed 's/### //g' b.txt >c.txt

s:取代,搭配正则
将### 开头的用空白取代,也就是去掉###。
如果不加g,只对第一个匹配,加了g,对所有匹配。

mysql binlog恢复 mysql binlog恢复删除的表数据_sed_02

sed 's#/.*#,#g' c.txt >d.txt

#用作分隔符.

以/开始的内容,用,替换。

加g,全部匹配替换。

mysql binlog恢复 mysql binlog恢复删除的表数据_mysql_03

sed 's#DELETE FROM#INSERT INTO#g' d.txt >e.txt

将delete from 语句改成 insert into 语句。

加g,全部匹配替换。

mysql binlog恢复 mysql binlog恢复删除的表数据_sed_04

sed 's#WHERE#SELECT#g' e.txt >f.txt

原理同上,可以一眼看出来。

mysql binlog恢复 mysql binlog恢复删除的表数据_mysql_05

sed -r 's#(@11=.*)(,)#\1;#g' f.txt >h.txt

-r:将正则表达式中的需要转义的字符设置成不需要转义(加)
https://blog.51cto.com/asmboy001/182290 括号用来匹配连续出现的内容。
.*标识匹配除换行符\n外的任何单元符。
为了把,去掉,单独(,)
\1是用来取()表示符的第一个。并在后面拼接上;
即:匹配a11=开头的,以,结尾的,把,替换成;
注意:这里的11,其实是表字段的数量,把最后一个后面加分号,很好理解。
mysql binlog恢复 mysql binlog恢复删除的表数据_sed_06

sed -r ‘s#(@.=)(.)#\2#g’ h.txt >>aa.sql

同上,可以理解,是只拿@.=后面的内容,也就是说把@.=删掉。

mysql binlog恢复 mysql binlog恢复删除的表数据_mysql binlog恢复_07

sed -i ‘$a commit;’ aa.sql
-i:拼接。
这就不截图了。
完成。

执行sql

可以焦急地等待数据被恢复了。
然后发现数据恢复失败了,部分格式转换错误。

排查问题

查看对应数据,发现这条原数据里面某个字段的值是斜杠/
经过回看,发现在c.txt转d.txt的时候,

@22='/' /* VARSTRING(128) meta=128 nullable=1 is_null=0 */

变成了

@22=',

改正则:
原:

sed 's#/.*#,#g' c.txt >d.txt

现在:

sed 's#/\*.*#,#g' c.txt >d.txt

加上了/*的前缀匹配。解决.

总结

可以看到,在最后由于数据内容的问题,我们可能需要在上面的正则上做进一步的修改,这就要求我们对sed和正则有充分的了解,这块还需要深入学习呀!
另外,数据被删除本来就是属于工作失误,可能影响范围会很广(跟工资成正比,嘻嘻)。如果刚删除直接要恢复的话,还是直接binlog恢复到最近的index最好。但是如果错过了最佳抢救时间,只能按我这么来了(当然,我这也是单表的批量delete,操作,恢复还算方便,只适用于部分情况),所以最好是永远不要碰到这种情况。
提醒一下自己,之后在做数据的更改的时候,必须要备份,备份,备份!