Mysql利用binlog日志恢复数据实战案例
作者:Le...
Mysql binlog核心配置解析
查看binlog日志核心配置项
输入以下命令查询binlog相关配置信息
mysql> show variables like '%log_bin%';
执行结果:
+---------------------------------+------------------------------------------------+ | Variable_name | Value | +---------------------------------+------------------------------------------------+ | log_bin | ON | | log_bin_basename | /usr/local/mysql8.0.39/mysql/data/mysql-bin | | log_bin_index | /usr/local/mysql8.0.39/mysql/data/binlog.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | | sql_log_bin | ON | +---------------------------------+------------------------------------------------+
binlog核心配置说明
(1)log_bin
字段含义:全局控制 MySQL 是否开启二进制日志的总开关。
取值为
ON时,MySQL 会记录所有对数据的修改操作(如 INSERT/UPDATE/DELETE、表结构变更等)到 binlog 文件,用于 数据恢复(通过 binlog 回滚或重做操作)和 主从复制(主库通过 binlog 向从库同步数据)。取值为
OFF时,完全关闭 binlog,不记录任何修改操作(生产环境建议开启,除非是纯只读库)。
(2)log_bin_basename
字段含义:指定二进制日志文件的 基础路径和基础名称(即 binlog 文件的 “前缀”)。
实际生成的 binlog 文件会在基础名称后添加 序号后缀(如
.000001、.000002),形成完整文件名。示例中
log_bin_basename = /usr/local/mysql8.0.39/mysql/data/mysql-bin,表示 binlog 文件会生成在/usr/local/mysql8.0.39/mysql/data/目录下,文件名格式为mysql-bin.000001、mysql-bin.000002等(文件满或执行flush logs时会生成新序号的文件)。
(3)sql_log_bin
字段含义:会话级 控制当前数据库会话是否记录 binlog(优先级高于全局 log_bin)。
取值为
ON时,当前会话的修改操作会记录到 binlog(继承全局log_bin=ON的行为);取值为OFF时,当前会话的修改操作 不记录 binlog(临时关闭当前会话的 binlog 记录,不影响其他会话)。用途:例如执行临时数据修复、测试操作时,可临时执行
SET sql_log_bin = OFF;,避免这些操作被同步到从库或记录到 binlog(执行后需注意还原,防止遗漏正常操作)。
查看当前所有二进制日志(binlog)文件信息
show master logs;
执行结果:
+------------------+------------+-----------+ | Log_name | File_size | Encrypted | +------------------+------------+-----------+ | mysql-bin.000006 | 1073742453 | No | | mysql-bin.000007 | 142945256 | No | +------------------+------------+-----------+
结果显示当前有 2 个 binlog 文件,其中较早的 000006 已接近 1GB 上限,后续会自动生成新文件。
查看当前正在活跃的二进制日志(binlog)信息
mysql> show master status;
执行结果:
+------------------+-----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+-----------+--------------+------------------+-------------------+ | mysql-bin.000007 | 142985195 | | | | +------------------+-----------+--------------+------------------+-------------------+
File :当前正在写入的binlog文件名。这里为 mysql-bin.000007
Position:当前活跃 binlog 文件中的偏移量(字节位置),表示主库已经往 File 中写的字节的位置。
Binlog_Do_DB: 仅记录指定数据库的 binlog(白名单)为空表示所有数据库的修改都被记录。
Binlog_Ignore_DB :不记录指定数据库的 binlog(黑名单),为空表示不忽略任何库。
Executed_Gtid_Set: 已执行的 GTID(全局事务 ID)集合,为空表示未启用 GTID 复制模式(使用传统的 “基于位置的复制”)。
以上是数据库中binlog日志相关配置的解析,下面移步navivate,看一个小小的数据库误删除恢复案例。
实战案例
案例1:恢复误删除的数据库

这里首先创建了一个名为binlog_demo_1的数据库,其中包含了一张user表,插入了一条信息。但是忘截图了,等恢复后再看哈。

接着将数据库不小心删掉,下面进行数据库及其中数据的恢复实战。
(1)获取mysql正在写入的binlog文件

查询当前数据库正在写入的binlog文件,结果显示文件名为mysql-bin.000007,其中已经写了
143233008字节的信息。
(2)查看binlog文件具体日志信息。
命令: SHOW BINLOG EVENTS IN 'your binlog filename';

BEGIN代表事务开启,COMMIT或ROLLBACK表示事务结束。
(3)查看binlog日志,确定恢复数据库的记录。

这里可以找到创建数据库的日志记录。

可以找到删除数据库的日志记录,这两条记录之间包含了该数据库中所有表的DML(数据操作)和DDL(表结构操作)记录,重新执行这两条记录之间的所有SQL(不包括删除数据库的sql)便可恢复该数据库。
(4)确定position范围


Pos指起始位置,End_log_pos指结束位置。可以看到恢复binlog_demo_1的pos起点为 143117334 终点为 143164854(143164854 - 143164987这条不能再执行,不然数据库又被删了)
(5)利用mysql官方工具 mysqlbinlog进行数据恢复

进入mysql的bin目录,可以看到mysqlbinlog。但是想要恢复,就必须知道binlog日志文件的位置,还记得怎么去找到吗?
log_bin_basename 含义是日志存储的基础位置和基础前缀,使用命令:
mysql> show variables like 'log_bin_basename';

可以看到文件基础位置/usr/local/mysql8.0.39/mysql/data,基础前缀为mysql-bin,结合上面的binlog文件名,便可定位到我们需要的binlog日志文件。

在恢复之前,登录mysql客户端,关闭当前会话的binlog日志记录,可以避免恢复操作产生的记录对原binlog日志造成污染,也防止从节点同步数据时重复执行sql导致的异常。执行以下命令。
mysql> SET sql_log_bin = OFF;
关闭当前会话后,紧接着就可以进行数据恢复了,因为前面仅针对当前会话关闭binlog记录。如果退出就失效了,所以重新开一个终端,进入到mysql的bin目录下,执行恢复命令:
mysqlbinlog --no-defaults --start-position=143117334 --stop-position=143164854 --database=binlog_demo_1 /usr/local/mysql8.0.39/mysql/data/mysql-bin.000007 | mysql -uroot -p
mysqlbinlog
--no-defaults # 1. 不加载默认配置文件
--start-position=143117334 # 2. 起始位置:从binlog的该字节位置开始解析
--stop-position=143164854 # 3. 结束位置:解析到binlog的该字节位置停止
--database=binlog_demo_1 # 4. 筛选数据库:只解析该数据库的操作
/usr/local/mysql8.0.39/mysql/data/mysql-bin.000007 # 5. 目标binlog文件路径
| mysql -u<username> -p<password> # 6. 管道:将解析出的SQL传递给mysql客户端执行
最后记得执行下行命令,重新开启会话binlog日志。
mysql> SET sql_log_bin = ON;
(6)检验恢复结果

可以看到binlog_demo_1数据库已被恢复。

数据库中的数据也都被一并恢复。
案例2:恢复表中误删除的记录。

在user表中新增一条记录(2,xiaoming)

现在再次不小心把该条记录删掉。开始进行恢复操作演示。
(1)确定binlog_format模式
MySQL 的 binlog_format 有三种模式:STATEMENT(语句模式)、ROW(行模式)、MIXED(混合模式)。不同模式的 binlog 记录内容差异极大,因此使用 mysqlbinlog 解析时需要匹配不同的策略。以下是详细说明:
| 格式 | 记录内容 | 优势 | 劣势 | 适用场景 | |
|---|---|---|---|---|---|
| STATEMENT | 记录完整的 SQL 语句,不包含具体行数据。 | 日志体积小,可读性高(直接看 SQL) |
| 简单的批量操作,无复杂函数。 | |
| ROW | 不记录 SQL 语句,仅记录每行数据的变化(如 “某行被修改前 / 后的值”)。 | 主从一致性高,精确记录每行变化。 | 日志体积大,可读性差(默认 base64 编码)。 | 数据一致性要求高的场景(如金融)。 | |
| MIXED | 自动切换模式:简单操作记 STATEMENT,复杂操作(如含非确定性函数)记 ROW。 | 平衡体积和一致性。 | 解析时需同时处理两种格式。 | 大多数通用场景。 |
查看mysql配置文件,通常名为 my.cnf 或 my.ini,确定 binlog_format模式。

这里演示的是ROW模式,各位小伙伴一定要确认好自己的mysql binlog_format模式。
(2)确定对应mysqlbinlog解析策略
1)TATEMENT 模式 解析
特点:binlog 中直接存储明文 SQL,无需额外解码。
解析命令(基础参数即可):
mysqlbinlog \ --no-defaults \ # 避免配置文件冲突 --start-datetime='2025-10-20 10:52:00' \ # 时间过滤 --stop-datetime='2025-10-20 10:54:00' \ --database=目标库名 \ # 库名过滤 原始binlog文件路径 \ > 解析结果.sql
解析结果可直接看到完整SQL语句,例如:
DELETE FROM `test`.`user` WHERE id = 123; UPDATE `test`.`order` SET status = 1 WHERE create_time < '2025-10-20';
2)ROW 模式解析(最复杂,需解码)
特点:binlog 中以 base64 编码存储行数据变化,不显示 SQL 语句,需解码才能看到具体字段值。
解析命令(必须加解码参数):
mysqlbinlog \ --no-defaults \ --base64-output=decode-rows \ # 核心:解码 base64 编码的行数据 --verbose \ # 可选:显示字段类型注释(如 `@1=123 /* INT */`) --start-datetime='2025-10-20 10:52:00' \ --stop-datetime='2025-10-20 10:54:00' \ --database=目标库名 \ 原始binlog文件路径 \ > 解析结果.sql
解析结果:显示每行数据的变化,例如删除操作:
### DELETE FROM `test`.`user` ### WHERE ### @1=123 /* INT meta=0 nullable=0 is_null=0 */ -- 字段1(id) ### @2='张三' /* VARCHAR(20) meta=65535 nullable=0 is_null=0 */ -- 字段2(name) ### @3='2025-10-20 10:53:00' /* DATETIME meta=0 nullable=0 is_null=0 */ -- 字段3(create_time)
3) MIXED 模式解析(兼容两种策略)
特点:部分操作是 STATEMENT 格式(明文 SQL),部分是 ROW 格式(编码行数据)
解析命令:按 ROW 模式的命令解析(兼容 STATEMENT 格式):
mysqlbinlog \ --no-defaults \ --base64-output=decode-rows \ # 解码 ROW 部分,不影响 STATEMENT 部分 --verbose \ --start-datetime='时间范围' \ 原始binlog文件路径 \ > 解析结果.sql
解析结果:同时包含明文 SQL(STATEMENT 部分)和行数据(ROW 部分),例如:
-- STATEMENT 格式的操作
INSERT INTO `test`.`log` (content) VALUES ('system start');
-- ROW 格式的操作
### UPDATE `test`.`user`
### WHERE
### @1=456 /* INT */
### @2='李四' /* VARCHAR */
### SET
### @1=456
### @2='李四_updated' /* VARCHAR */关键:同时处理两种格式的内容 ——SQL 语句直接查看,行数据按 ROW 模式的方法解析
记住:只要 binlog 中可能包含 ROW 格式内容(如 rbr_only=yes),就必须加 --base64-output=decode-rows,否则无法看到具体数据变化。
(3) 使用mysqlbinlog策略进行日志解析
博主的mysql binlog_formate=ROW,各位小伙伴确定好自己mysql的日志模式,选择相应的策略。

将解析结果保存至recovery_detail.sql
(4)定位误删除的记录
根据关键字(DELETE FROM `database_name`)定位操作

(5) 数据转换并恢复数据
将DELETE转为INSERT

执行sql,恢复数据。


数据已被恢复。
总结
到此这篇关于Mysql利用binlog日志恢复数据的文章就介绍到这了,更多相关Mysql binlog日志恢复数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
