MySQL binlog 恢复数据

Last Modified: 2023/09/25

概述

本文将会带大家使用 mysql binlog 恢复被误删的数据,或者恢复某个粗心大意的同事手抖而更新错的数据。没有你说不定他就要提桶跑路了,答应我为了你的同事好好学习下如何使用 mysql binlog 恢复数据。

查看 binlog 是否开启以及 binlog 格式

既然是利用 binlog 来恢复数据,那么肯定要开启 binlog,先连上数据库,然后查看 binlog 是否开启,以及当前 binlog 的格式。

查看 binlog 是否开启,执行下面的 sql,如果是 ON 则表示开启,OFF 表示未开启。

show variables like 'log_bin';

查看当前 binlog 格式,可使用下面的 sql

show variables like 'binlog_format';

binlog 总共有三种格式,三种格式各有优缺点,本文不会讲述这三个格式的区别,感兴趣的请自行查阅。我们希望使用的格式为 ROW

如果数据库没有备份,binlog 也没打开,那么基本可以提桶跑路了。

开启 binlog

下面以 linux 发行版 Ubuntu 为例说明如何开启 binlog,找到 /etc/mysql/my.cnf 中加入:

[mysqld]
# Must be unique integer from 1-2^32
server-id        = 1
# Row format required for ZongJi
binlog_format    = row
# Directory must exist. This path works for Linux. Other OS may require
# different path.
log_bin          = /var/log/mysql/mysql-bin.log

然后便是重启 mysql 使其生效

service mysql stop
service mysql start

使用 binlog 恢复误删数据

为了方便说明,假设有一张 vip 表,经过日积月累,已经累计高达 3 条宝贵数据:

现在轮到你的粗心同事张大宽粉墨登场。他在执行删除时,忘加条件了,当他执行完下面的语句才反应过来,于是慌慌张张找到你,让你无论如何拉兄弟一把。

delete from vip;

想到这个高达几个小目标的宝贵数据,你赶紧得想办法恢复数据。先执行以下 sql,看看 binlog 目前的情况,由于刚刚事发,通常找到最新的那个 binlog 即可

接下来便是下载 binlog,下载 binlog 可以利用 mysqlbinlog 备份命令完成

mysqlbinlog --read-from-remote-server --raw --host=192.168.8.8 --port=3306 --user=repl -p  mysql-bin.000001
# 或者
mysqlbinlog -R --raw --host=192.168.8.8 --port=3306 --user=root -p  mysql-bin.000001

注:这里的 host、user 和 binlog 文件名称等参数需要根据实际情况修改。

下载完 binlog 之后,便是使用 mysqlbinlog 命令将 binlog 转换成可读的 sql 形式,命令如下:

# 转换的结果存放在 dump.sql 中
mysqlbinlog -v mysql-bin.000001 > ./dump.sql

使用编辑器,打开 dump.sql,并询问你的同事误删除大概发生的时间,确定删除的内容。经过一番搜索,最终找到了发生这个不幸的时间在 21:28:20,你心想原来都这么晚了,脑子迷糊了也是有可能的。

# at 47663
#230924 21:28:20 server id 1  end_log_pos 47737 CRC32 0xd2311fee 	Query	thread_id=40	exec_time=0	error_code=0
SET TIMESTAMP=1695562100/*!*/;
BEGIN
/*!*/;
# at 47737
#230924 21:28:20 server id 1  end_log_pos 47792 CRC32 0xf93c16fc 	Table_map: `vip`.`vip` mapped to number 101
# has_generated_invisible_primary_key=0
# at 47792
#230924 21:28:20 server id 1  end_log_pos 47875 CRC32 0xd80b456b 	Delete_rows: table id 101 flags: STMT_END_F

BINLOG '
dDkQZRMBAAAANwAAALC6AAAAAGUAAAAAAAEAA3ZpcAADdmlwAAMDDwMCUAAGAQEAAgEt/BY8+Q==
dDkQZSABAAAAUwAAAAO7AAAAAGUAAAAAAAEAAgAD/wABAAAABuW8oOS4iRQAAAAAAgAAAAbmnY7l
m5sVAAAAAAMAAAAG546L5LqUFgAAAGtFC9g=
'/*!*/;
### DELETE FROM `vip`.`vip`
### WHERE
###   @1=1
###   @2='张三'
###   @3=20
### DELETE FROM `vip`.`vip`
### WHERE
###   @1=2
###   @2='李四'
###   @3=21
### DELETE FROM `vip`.`vip`
### WHERE
###   @1=3
###   @2='王五'
###   @3=22
# at 47875
#230924 21:28:20 server id 1  end_log_pos 47906 CRC32 0x35a7f812 	Xid = 602
COMMIT/*!*/;

这不就好了吗,定位到了删除的地方,删除的具体内容全都记录在案,剩下的工作便是着手恢复了。如果真的只有三条数据,那便可以手动恢复了。实际工作中往往删除的数据量很大,那么可以借助 MyUndelete.py 完成恢复。

可以看出开始删除的语句起始位置为 47663,是一个 BEGIN 语句,终止位置为 47906,为 COMMIT 语句。有了开始和结束位置,便可以使用 MyUndelete 命令恢复。

./MyUndelete.py -b mysql-bin.000001 -s 47663 -e 47906

这个工具除了可以恢复误删的数据,也可以对误更新和误插入的数据进行恢复。个人感觉这个工具有点虎,你用上面的命令之后,数据被直接恢复到数据库,你没有机会检查恢复数据的 sql 究竟是否 OK。

另外工具稍显久远,使用 python 2.x 写的。另外需要提一句,使用本命令之前需要先配置好 Mysql 的用户名和密码,不支持通过命令行传递用户名和密码。配置通常在 /etc/mysql/my.cnf,在该文件中加入:

[client]
user=yourusername
password=yourpwd

其他数据恢复工具

这里只是列出一些 binlog 数据恢复工具,不会做过多说明,如有需要,直接去看工具文档即可。

1、binlog2sql

可以使用下面的命令生成回滚 sql,注意下面的这个命令不需要下载 binlog,直接连 mysql 生成回滚 sql。

# 生成回滚 sql
python ./binlog2sql.py --flashback -h127.0.0.1 -P3306  -uroot -p --start-file='mysql-bin.000001' --start-position=47663 --stop-position=47906 > rollback.sql
# 导入 mysql
mysql -h127.0.0.1 -P3306 -uroot -p'123456' < rollback.sql

项目地址:https://github.com/danfengcao/binlog2sql

2、my2sql

my2sql 是 go 实现的,速度比 binlog2sql 快很多,使用 my2sql 生成回滚 sql 的方法如下:

./my2sql -user root -password 123456 -mode file -local-binlog-file /path/to/mysql-bin.000001 -work-type rollback --start-file /path/to/mysql-bin.000001 -start-pos 47663 -stop-pos 47906 -output-dir /tmp/abc

-worktype 还支持 2sql,2sql 不会生成回滚 sql,而是直接展示原始 sql。

项目地址:https://github.com/liuhr/my2sql

有问题吗?点此反馈!

温馨提示:反馈需要登录