使用 mysqlbinlog 分析 binlog 恢复误删除或修改的数据

lz 1年前 ⋅ 1247 阅读

一、mysqlbinlog

在 mysql 中binlog 记录着所有的DDL 和 DML,前提是开启了 binlog,这个时候如果我们误删除了数据或者误修改了数据,就可以通过 binlog 日志文件进行查找恢复。但是 binlog 是以二进制的方式进行存储的,我们直接查看的话并不能看到我们想要的数据,而 mysqlbinlog 就是提供给我们方便查询binlog的工具,我们借助它可以根据时间段或者位置进行快速定位,并且还可以连接远程服务器的 mysql 查看 binlog 信息。

首先在开始实验前,请确保自己的mysql 已经开启了 binlog ,这里我配置的 binlog 的格式为 ROW 模式。

查看是否开启 binlog:

show variables like '%log_bin%';

查看 binlog 输出格式:

show variables like '%binlog_format%';

上面开启好,就可以进行下面的实验了。

二、少量数据误删除修改数据恢复方案

环境准备

首先新建一张表,下面基于该表进行实验:

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `phone` varchar(255) DEFAULT NULL,
  `mail` varchar(255) DEFAULT NULL,
  `lock` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

首先向表中添加几条数据:

INSERT INTO `testdb`.`user`(`name`, `phone`, `mail`, `lock`) VALUES ('zhangsan', '110', '110@qq.com', '0');
INSERT INTO `testdb`.`user`( `name`, `phone`, `mail`, `lock`) VALUES ('lisi', '111', '111@qq.com', '0');
INSERT INTO `testdb`.`user`(`name`, `phone`, `mail`, `lock`) VALUES ('wangwu', '112', '112@qq.com', '0');
INSERT INTO `testdb`.`user`(`name`, `phone`, `mail`, `lock`) VALUES ('xiaoming', '113', '113@qq.com', '0');

首先查看下当前正在写入的 binlog 文件:

show master status;

也可以查看下当前有多少个 binlog 日志文件了:

show binary logs;

某几条数据误修改

如果只是某几条数据误操作,我们可以通过日志拿到原有的数据进行恢复,将 zhangsan 和 lisi 的phone 和 mail 修改为 001:

下面在 SQL 控制台查看下 binlog 信息:

show binlog events in 'binlog.000002';

这样还不能看出刚才修改前的内容,下面就要使用 mysqlbinlog 工具进行分析了,首先进入到 binlog 日志的位置,我们根据时间点过滤下:

mysqlbinlog --no-defaults --base64-output=decode-rows -v 
--start-datetime="2022-03-13 19:00:00" --stop-datetime="2022-03-13 19:10:00" ./binlog.000002 

其中 --no-defaults 表示不使用配置文件中( my.cnf 里配的 [client] )的参数,可以避免有些 mysqlbinlog 没有的参数导致的失败,--base64-output=decode-rows 解码方式,不加的话看到的是 base64 之后的,-v 显示sql 语句,也可以 -vv 显示sql语句和类型,--start-datetime 和 --stop-datetime 表示开始和结束时间,或者使用 --start-position 和 --stop-position 表示起始位置,如果是解析多个 binlog,则 --start-position 只对第一个 binlog 生效,--stop-position 只对最后一个 binlog 生效。

从这里就看到了修改前的数据,也可以将结果输出到文件中,使用 -r 即可:

mysqlbinlog --no-defaults --base64-output=decode-rows -v 
--start-datetime="2022-03-13 19:00:00" --stop-datetime="2022-03-13 19:10:00" ./binlog.000002 -r log.txt

某数据误删除

误删除和上面同样的操作方式,下面将 wangwu 和 xiaoming 的数据进行删除:

再次使用 mysqlbinlog 进行分析:

mysqlbinlog --no-defaults --base64-output=decode-rows -v 
--start-datetime="2022-03-13 19:18:00" --stop-datetime="2022-03-13 19:20:00" ./binlog.000002

同样找到了修改前的数据。

三、大批量数据误删除和修改

上面少量的数据,可以通过查看 binlog 的日志文件获取到修改前的内容进行恢复,如果是大批量的情况下,比如误删除了数据库或表,或者批量删除修改数据 where 条件写错,这种情况下我们就需要结合备份和 binlog 文件进行恢复了。首先对数据库的备份应该是目前大多数公司都在做的事情吧,比如按月的全量备份,按周的增量备份等,对于mysql 备份也是多种的方案可以选择,比如我们可以使用自带的 mysqldump 工具。

下面演示下误删除表和误修改 where 条件错误的情况:

误删除表恢复方案

首先对上面创建的表恢复到最初的状态:

首先这里使用 mysqldump 对该数据库进行备份,模拟全量备份:

mysqldump -u root -p testdb > testdb.sql

此时最好刷新下日志,让下面的操作都写入一个新的日志中:

flush logs;

然后再查看下当前的日志文件:

show master status;

下面我们对表进添加几条数据模拟后续的操作:

再修改下zhangsan的 phone 和 mail 字段 :

下面假如不小心把该表给删除掉了:

DROP TABLE user; 

那现在我们开始恢复,在恢复前先刷新下当前的日志,让后面的操作都写在新的日志中,后面对 binlog.000002 进行恢复就可以了。

flush logs;

当前写入的已经是 binlog.000003 了,下面先对之前备份的数据进行恢复。

source D:\software\MySQL\mysql-8.0.25-winx64\bak\testdb.sql

现在恢复到之前的数据,那下面添加和修改的数据就需要通过 binlog.000002 进行恢复了,下面使用 mysqlbinlog 查看下日志内容:

mysqlbinlog --no-defaults --base64-output=decode-rows -v -d testdb ./binlog.000002 

可以看到刚才写入和修改的数据:

 

由于一张表的数据可能较大,我们再通过人工的方式恢复,工作量就大了,这里我们可以思考下,mysql 在做主从复制的时候就是同步的 binlog 文件内容,进行数据同步的,那现在是不是也可以把 binlog 的内容给 当前数据库再执行一次,不就相当于做了数据恢复了吗。

但是需要注意的是,最后的删除表的指令也记在了该 binlog 中,所以要把该指令排除在外,通过日志的分析,可以定位到该 删除指令记录的位置:

所以我们要恢复 位置 2317 前面的数据,下面使用 mysqlbinlog 查出 2317 前面的,并交给 mysql 执行:

mysqlbinlog --no-defaults --stop-position=2317 
-d testdb ./binlog.000002 | mysql -u root -p -v testdb

下面再查看数据库中的内容:

已经恢复到之前的数据。

四、扩展

远程查看 binlog:

mysqlbinlog -u root -p root -h 192.168.0.1 -P 3306 --no-defaults 
--base64-output=decode-rows -v --start-datetime="2022-03-13 18:08:00" 
--stop-datetime="2022-03-13 18:10:00" ./binlog.000001 > test2.sql

条件筛选

mysqlbinlog --base64-output=decode-rows  -v --no-defaults
 --database=raceEnroll  binlogs.000078 |grep zhangsan |more

重置所有日志(慎用,会清除原有的日志文件)

reset master;

刷新日志,开启一个新的日志文件:

Flush logs;

 

--end--

 

版权 本着开源共享、共同学习的精神,本文转载自 https://blog.csdn.net/qq_43692950/article/details/123463563 , 如果侵权之处,请联系博主进行删除,谢谢~