具体的配置方式网上有很多,我就不写了,下面附上我的配置。
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 三种模式的区别
分为三步:
./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 一起运行
保留以###开始的行数据。
sed 's/### //g' b.txt >c.txt
s:取代,搭配正则
将### 开头的用空白取代,也就是去掉###。
如果不加g,只对第一个匹配,加了g,对所有匹配。
sed 's#/.*#,#g' c.txt >d.txt
#用作分隔符.
以/开始的内容,用,替换。
加g,全部匹配替换。
sed 's#DELETE FROM#INSERT INTO#g' d.txt >e.txt
将delete from 语句改成 insert into 语句。
加g,全部匹配替换。
sed 's#WHERE#SELECT#g' e.txt >f.txt
sed -r 's#(@11=.*)(,)#\1;#g' f.txt >h.txt
-r:将正则表达式中的需要转义的字符设置成不需要转义(加)
https://blog.51cto.com/asmboy001/182290
括号用来匹配连续出现的内容。
.*标识匹配除换行符\n外的任何单元符。
为了把,去掉,单独(,)
\1是用来取()表示符的第一个。并在后面拼接上;
即:匹配a11=开头的,以,结尾的,把,替换成;
注意:这里的11,其实是表字段的数量,把最后一个后面加分号,很好理解。
sed -r ‘s#(@.=)(.)#\2#g’ h.txt >>aa.sql
同上,可以理解,是只拿@.=后面的内容,也就是说把@.=删掉。
sed -i ‘$a commit;’ aa.sql
-i:拼接。
这就不截图了。
完成。
可以焦急地等待数据被恢复了。
然后发现数据恢复失败了,部分格式转换错误。
查看对应数据,发现这条原数据里面某个字段的值是斜杠/
经过回看,发现在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,操作,恢复还算方便,只适用于部分情况),所以最好是永远不要碰到这种情况。
提醒一下自己,之后在做数据的更改的时候,必须要备份,备份,备份!