MySQL 二进制日志binlog解析

一、binlog2sql工具

一)、叙述

1.描述

binlog2sql是一款用于解析 MySQL 二进制日志(binlog)的工具,通过它能够把 binlog 转换为可直接执行的 SQL 语句或者反向 SQL(用于数据回滚)。 适用的数据库:

  • MySQL
    binlog2sql 原生支持 MySQL 5.6+ 版本,兼容 InnoDB、MyISAM 等存储引擎,需开启 binlog 功能(配置 log-bin=mysql-bin)。
  • MariaDB
    作为 MySQL 的分支,MariaDB 通常也能使用 binlog2sql,但需确保 binlog 格式兼容(如 ROW 格式)。
  • TokuDB/Percona Server
    基于 MySQL 内核的数据库(如 TokuDB、Percona Server)在使用 MySQL 原生 binlog 时也可兼容。

2.binlog 格式要求

binlog2sql 对 binlog 格式有严格要求:

  • 推荐格式:ROW
    记录每行数据的变更细节,支持 --flashback 反向 SQL 生成。
    配置:binlog_format = ROW
  • 支持格式:MIXED
    混合模式,部分语句可能转为 STATEMENT 格式,需确保关键操作使用 ROW 模式。
  • 不支持格式:STATEMENT
    仅记录 SQL 语句,无法准确恢复数据变更(如 UPDATE 无前后值对比)。

3.限制(对比mysqlbinlog)

  • mysql server必须开启,离线模式下不能解析
  • 参数 binlog_row_image 必须为FULL,暂不支持MINIMAL
  • 解析速度不如mysqlbinlog

4.优点(对比mysqlbinlog)

  • 纯Python开发,安装与使用都很简单
  • 自带flashback、no-primary-key解析模式,无需再装补丁
  • flashback模式下,更适合闪回实战
  • 解析为标准SQL,方便理解、筛选
  • 代码容易改造,可以支持更多个性化解析

二)、安装

1.安装前提条件

  • Python 环境
    需要 Python 3.6+,建议使用 Python 3.8 或更高版本。
  • MySQL 客户端库
    Ubuntu/Debian:sudo apt-get install python3-dev libmysqlclient-dev
    CentOS/RHEL:sudo yum install python3-devel mysql-devel
    macOS(使用 Homebrew):brew install mysql-connector-c

2.安装 binlog2sql

# 克隆仓库
git clone https://github.com/danfengcao/binlog2sql.git
cd binlog2sql

# 安装依赖包
pip3 install -r requirements.txt

git下载地址
博客下载地址
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/974ec168c96e462b8e5c021dbb341478.png
在这里插入图片描述

3.验证安装

python binlog2sql.py --help

在这里插入图片描述

4.对于生产环境数据恢复,推荐流程:

生产binlog文件 → 拷贝到测试环境 → 建立相同表结构 → 使用binlog2sql解析

5.用户权限说明

  • select:需要读取server端information_schema.COLUMNS表,获取表结构的元信息,拼接成可视化的sql语句
  • super/replication client:两个权限都可以,需要执行’SHOW MASTER STATUS’,
    获取server端的binlog列表
  • replication slave:通过BINLOG_DUMP协议获取binlog内容的权限
#精确检查 binlog2sql 所需权限
SELECT 
   User, 
   Host,
   (SELECT_priv = 'Y') AS has_select,
   (Super_priv = 'Y') AS has_super,
   (Repl_client_priv = 'Y') AS has_repl_client,
   (Repl_slave_priv = 'Y') AS has_repl_slave   
FROM mysql.user    
WHERE User = 'username' AND Host = 'host';

在这里插入图片描述

6. 创建符合 binlog2sql 要求的用户

CREATE USER 'binlog2sql_user'@'%' IDENTIFIED BY 'your_password';   
GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO 'binlog2sql_user'@'%';
FLUSH PRIVILEGES;   

三)、选项说明

binlog2sql 是一个用于解析 MySQL 二进制日志(binlog)并生成原始 SQL 语句的工具,常用于误删数据恢复、审计等场景。

下面是 binlog2sql 的常用选项说明(以当前主流版本 danfengcao/binlog2sql 为例):


✅ 基本语法

python binlog2sql.py [options]

📌 核心参数说明

🔹 连接数据库相关参数-必要参数

参数说明
-h, --hostMySQL 主机地址,默认为 127.0.0.1
-P, --portMySQL 端口,默认为 3306
-u, --userMySQL 用户名(必须提供)
-p, --passwordMySQL 密码(必须提供)

示例:

-h 192.168.1.10 -P 3306 -u root -p 'your_password'

🔹 指定 binlog 文件范围

参数说明
--start-file起始 binlog 文件名(例如:mysql-bin.000001
--end-file结束 binlog 文件名(可选)
--start-position, --start-pos起始位置偏移量(默认从文件开头开始)
--end-position, --end-pos结束位置偏移量(可选)

示例:

--start-file='mysql-bin.000001' --start-pos=1234 --end-file='mysql-bin.000002' --end-pos=5678

🔹 时间范围过滤

参数说明
--start-datetime开始时间(格式如:'2025-06-30 10:00:00'
--end-datetime结束时间(格式同上)

示例:

--start-datetime='2025-06-30 10:00:00' --end-datetime='2025-06-30 12:00:00'

🔹 数据库和表过滤

参数说明
-d, --databases指定数据库名(多个用逗号分隔)
-t, --tables指定表名(多个用逗号分隔),需配合 -d 使用

示例:

-d test_db -t user,order

🔹 输出控制

参数说明
--only-sql只输出 SQL 语句,不显示其他信息
--no-primary-key不在 INSERT 中输出主键字段
--flashback生成回滚 SQL(用于恢复删除或更新操作)
--stop-never持续监听最新的 binlog 内容(适用于实时监控)

🧾 示例命令

示例 1:解析出回滚SQL

  • 按时间倒序输出能抵消原始操作的逆向SQL
  • 专门用于数据恢复场景
  • 每条SQL都带有原操作的位置和时间注释
shell> python binlog2sql.py --flashback -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttest3 --start-file='mysql-bin.000002' --start-position=763 --stop-position=1147

输出:
INSERT INTO `test`.`test3`(`addtime`, `data`, `id`) VALUES ('2016-12-10 13:03:38', 'english', 4); #start 981 end 1147
UPDATE `test`.`test3` SET `addtime`='2016-12-10 13:03:22', `data`='中文', `id`=3 WHERE `addtime`='2016-12-10 12:00:00' AND `data`='中文' AND `id`=3 LIMIT 1; #start 763 end 954

示例 2:解析出标准SQL

  • 按时间顺序正向输出binlog中的原始SQL语句
  • 真实记录数据库发生的所有变更(INSERT/UPDATE/DELETE)
  • 包含完整的执行时间、位置等信息注释
shell> python binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t test3 test4 --start-file='mysql-bin.000002'

输出:
INSERT INTO `test`.`test3`(`addtime`, `data`, `id`) VALUES ('2016-12-10 13:03:38', 'english', 4); #start 570 end 736
UPDATE `test`.`test3` SET `addtime`='2016-12-10 12:00:00', `data`='中文', `id`=3 WHERE `addtime`='2016-12-10 13:03:22' AND `data`='中文' AND `id`=3 LIMIT 1; #start 763 end 954
DELETE FROM `test`.`test3` WHERE `addtime`='2016-12-10 13:03:38' AND `data`='english' AND `id`=4 LIMIT 1; #start 981 end 1147

标准解析SQL与回滚SQL(Flashback)之间的核心区别。这里有一个稍微整理过的版本,以便更清晰地展示这些信息:

特性标准解析SQL回滚SQL(Flashback)
生成参数无特殊参数使用--flashback参数
SQL顺序时间正序时间倒序
INSERT处理原样输出INSERT语句转换为DELETE语句
DELETE处理原样输出DELETE语句转换为INSERT语句(带原数据)
UPDATE处理原样输出UPDATE语句生成逆向UPDATE(恢复旧值)
主要用途审计/分析数据恢复
安全性直接执行可能导致重复操作风险专门设计用于安全恢复
执行前检查必须仔细检查以避免意外后果仍建议检查,但相对风险较低

⚠️ 注意事项

  1. MySQL 配置要求

    • 必须开启 binlog(binlog_format=ROW
    • 推荐设置 binlog_row_image=FULL
    • 用户需要有 REPLICATION SLAVE 权限
    • > output.sql输出到指定文件
  2. 依赖库

    pip install -r requirements.txt
    
  3. 支持的事件类型

    • INSERT, UPDATE, DELETE(支持 flashback)

四)、应用案例

1.误删整张表数据,需要紧急回滚

test库tbl表原有数据
mysql> select * from tbl;
+----+--------+---------------------+
| id | name   | addtime             |
+----+--------+---------------------+
|  1 | 小赵   | 2016-12-10 00:04:33 |
|  2 | 小钱   | 2016-12-10 00:04:48 |
|  3 | 小孙   | 2016-12-13 20:25:00 |
|  4 | 小李   | 2016-12-12 00:00:00 |
+----+--------+---------------------+
4 rows in set (0.00 sec)

mysql> delete from tbl;
Query OK, 4 rows affected (0.00 sec)

20:28时,tbl表误操作被清空
mysql> select * from tbl;
Empty set (0.00 sec)

2.恢复数据步骤:

1)、登录mysql,查看目前的binlog文件
mysql> show master status;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000051 |       967 |
| mysql-bin.000052 |       965 |
+------------------+-----------+
2)、最新的binlog文件是mysql-bin.000052,我们再定位误操作SQL的binlog位置。误操作人只能知道大致的误操作时间,我们根据大致时间过滤数据。
shell> python binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttbl --start-file='mysql-bin.000052' --start-datetime='2016-12-13 20:25:00' --stop-datetime='2016-12-13 20:30:00'
输出:
INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-13 20:26:00', 4, '小李'); #start 317 end 487 time 2016-12-13 20:26:26
UPDATE `test`.`tbl` SET `addtime`='2016-12-12 00:00:00', `id`=4, `name`='小李' WHERE `addtime`='2016-12-13 20:26:00' AND `id`=4 AND `name`='小李' LIMIT 1; #start 514 end 701 time 2016-12-13 20:27:07
DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-10 00:04:33' AND `id`=1 AND `name`='小赵' LIMIT 1; #start 728 end 938 time 2016-12-13 20:28:05
DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-10 00:04:48' AND `id`=2 AND `name`='小钱' LIMIT 1; #start 728 end 938 time 2016-12-13 20:28:05
DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-13 20:25:00' AND `id`=3 AND `name`='小孙' LIMIT 1; #start 728 end 938 time 2016-12-13 20:28:05
DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-12 00:00:00' AND `id`=4 AND `name`='小李' LIMIT 1; #start 728 end 938 time 2016-12-13 20:28:05
3)、我们得到了误操作sql的准确位置在728-938之间,再根据位置进一步过滤,使用flashback模式生成回滚sql,检查回滚sql是否正确(注:真实环境下,此步经常会进一步筛选出需要的sql。结合grep、编辑器等)
shell> python binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttbl --start-file='mysql-bin.000052' --start-position=3346 --stop-position=3556 -B > rollback.sql | cat
输出:
INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-12 00:00:00', 4, '小李'); #start 728 end 938 time 2016-12-13 20:28:05
INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-13 20:25:00', 3, '小孙'); #start 728 end 938 time 2016-12-13 20:28:05
INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-10 00:04:48', 2, '小钱'); #start 728 end 938 time 2016-12-13 20:28:05
INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-10 00:04:33', 1, '小赵'); #start 728 end 938 time 2016-12-13 20:28:05
4)、确认回滚sql正确,执行回滚语句。登录mysql确认,数据回滚成功。
shell> mysql -h127.0.0.1 -P3306 -uadmin -p'admin' < rollback.sql

mysql> select * from tbl;
+----+--------+---------------------+
| id | name   | addtime             |
+----+--------+---------------------+
|  1 | 小赵   | 2016-12-10 00:04:33 |
|  2 | 小钱   | 2016-12-10 00:04:48 |
|  3 | 小孙   | 2016-12-13 20:25:00 |
|  4 | 小李   | 2016-12-12 00:00:00 |
+----+--------+---------------------+

二、my2sql工具

一)、叙述

1.描述

go版MySQL binlog解析工具,通过解析MySQL binlog ,可以生成原始SQL、回滚SQL、去除主键的INSERT SQL等,也可以生成DML统计信息。类似工具有binlog2sql、MyFlash、my2fback等,本工具基于my2fback、binlog_rollback工具二次开发而来。

2.用途

  • 数据快速回滚(闪回)

  • 主从切换后新master丢数据的修复

  • 从binlog生成标准SQL,带来的衍生功能

  • 生成DML统计信息,可以找到哪些表更新的比较频繁

  • IO高TPS高, 查出哪些表在频繁更新

  • 找出某个时间点数据库是否有大事务或者长事务

  • 主从延迟,分析主库执行的SQL语句

  • 除了支持常规数据类型,对大部分工具不支持的数据类型做了支持,比如json、blob、text、emoji等数据类型sql生成

3.产品性能对比

binlog2sql当前是业界使用最广泛的MySQL回滚工具,下面对my2sql和binlog2sql做个性能对比。

功能使用my2sql使用binlog2sql
生成回滚SQL1分40秒65分钟
生成原始SQL1分30秒50分钟
表DML及事务统计信息40秒不支持

4.限制

  • 使用回滚/闪回功能时,binlog格式必须为row,且binlog_row_image=full, DML统计以及大事务分析不受影响
  • 只能回滚DML, 不能回滚DDL
  • 使用rollback功能时,要解析的binlog段,表结构要保持一致(例如:解析mysql-bin.000001文件,此binlog文件的的表有add column或drop column操作,则执行rollback可能会执行异常)
  • 支持指定-tl时区来解释binlog中time/datetime字段的内容。开始时间-start-datetime与结束时间-stop-datetime也会使用此指定的时区, 但注意此开始与结束时间针对的是binlog event header中保存的unix timestamp。结果中的额外的datetime时间信息都是binlog event header中的unix timestamp
  • 此工具是伪装成从库拉取binlog,需要连接数据库的用户有SELECT, REPLICATION SLAVE, REPLICATION CLIENT权限
  • MySQL8.0版本需要在配置文件中加入default_authentication_plugin =mysql_native_password,用户密码认证必须是mysql_native_password才能解析

5.go安装

# 下载最新版 Go (请替换为最新版本号)
wget https://golang.org/dl/go1.21.1.linux-amd64.tar.gz

# 解压到 /usr/local
sudo tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz

# 设置环境变量
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
source ~/.bashrc

在这里插入图片描述
在这里插入图片描述

二)、安装

cd $GOPATH/src
git clone https://github.com/liuhr/my2sql.git
cd my2sql/
go build .
./my2sql version

博客下载地址
在这里插入图片描述
在这里插入图片描述

三)、选项说明

以下是你提供的参数说明整理成表格形式,便于查阅和理解:

参数名说明默认值
-U优先使用unique key作为where条件false
-mode模式选择:repl(伪装从库解析) 或 file(离线解析)repl
-local-binlog-file当模式为file时,指定binlog文件路径(可多个连续)
-add-extraInfo是否将额外信息(如db、table、时间、位置等)以注释形式加入SQL前false
-big-trx-row-limit n被认为是大事务的最小行数(即包含多少条SQL)500
-databases指定要解析的数据库列表,逗号分隔所有库
-tables指定要解析的表列表,逗号分隔所有表
-sql指定解析的SQL类型:insertupdatedelete全部解析
-doNotAddPrifixDb生成的SQL是否不带数据库名前缀false
-file-per-table为每个表生成一个独立的SQL文件false
-full-columns对于UPDATE/DELETE语句,是否使用全列构建WHERE或SET部分false
-ignorePrimaryKeyForInsert生成的INSERT语句是否忽略主键false
-output-dir指定输出结果的目录当前目录
-output-toScreen将结果打印到屏幕而不是写入文件false
-threads并发处理线程数8
-work-type工作类型:2sql(生成原始SQL)、rollback(生成回滚SQL)、stats(仅统计DML/事务)

四)、应用案例

1.解析出标准SQL

1)、根据时间点解析出标准SQL

#伪装成从库解析binlog
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode repl -work-type 2sql  -start-file mysql-bin.011259  -start-datetime "2020-07-16 10:20:00" -stop-datetime "2020-07-16 11:00:00" -output-dir ./tmpdir
#直接读取binlog文件解析
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode file -local-binlog-file ./mysql-bin.011259  -work-type 2sql  -start-file mysql-bin.011259  -start-datetime "2020-07-16 10:20:00" -stop-datetime "2020-07-16 11:00:00" -output-dir ./tmpdir

2)、根据pos点解析出标准SQL

#伪装成从库解析binlog
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode repl  -work-type 2sql  -start-file mysql-bin.011259  -start-pos 4 -stop-file mysql-bin.011259 -stop-pos 583918266  -output-dir ./tmpdir
#直接读取binlog文件解析
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306  -mode file -local-binlog-file ./mysql-bin.011259  -work-type 2sql  -start-file mysql-bin.011259  -start-pos 4 -stop-file mysql-bin.011259 -stop-pos 583918266  -output-dir ./tmpdir

2.解析出回滚SQL

1)、根据时间点解析出回滚SQL

#伪装成从库解析binlog
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode repl -work-type rollback  -start-file mysql-bin.011259  -start-datetime "2020-07-16 10:20:00" -stop-datetime "2020-07-16 11:00:00" -output-dir ./tmpdir
#直接读取binlog文件解析
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306  -mode file -local-binlog-file ./mysql-bin.011259 -work-type rollback  -start-file mysql-bin.011259  -start-datetime "2020-07-16 10:20:00" -stop-datetime "2020-07-16 11:00:00" -output-dir ./tmpdir

2)、根据pos点解析出回滚SQL

#伪装成从库解析binlog
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode repl -work-type rollback  -start-file mysql-bin.011259  -start-pos 4 -stop-file mysql-bin.011259 -stop-pos 583918266  -output-dir ./tmpdir
#直接读取binlog文件解析
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306   -mode file -local-binlog-file ./mysql-bin.011259  -work-type rollback  -start-file mysql-bin.011259  -start-pos 4 -stop-file mysql-bin.011259 -stop-pos 583918266  -output-dir ./tmpdir

3.统计DML以及大事务

1)、统计时间范围各个表的DML操作数量,统计一个事务大于500条、时间大于300秒的事务

#伪装成从库解析binlog
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306  -mode repl -work-type stats  -start-file mysql-bin.011259  -start-datetime "2020-07-16 10:20:00" -stop-datetime "2020-07-16 11:00:00"  -big-trx-row-limit 500 -long-trx-seconds 300   -output-dir ./tmpdir
#直接读取binlog文件解析
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode file -local-binlog-file ./mysql-bin.011259   -work-type stats  -start-file mysql-bin.011259  -start-datetime "2020-07-16 10:20:00" -stop-datetime "2020-07-16 11:00:00"  -big-trx-row-limit 500 -long-trx-seconds 300   -output-dir ./tmpdir

2)、统计一段pos点范围各个表的DML操作数量,统计一个事务大于500条、时间大于300秒的事务

#伪装成从库解析binlog
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306  -mode repl -work-type stats  -start-file mysql-bin.011259  -start-pos 4 -stop-file mysql-bin.011259 -stop-pos 583918266  -big-trx-row-limit 500 -long-trx-seconds 300   -output-dir ./tmpdir
#直接读取binlog文件解析
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode file -local-binlog-file ./mysql-bin.011259  -work-type stats  -start-file mysql-bin.011259  -start-pos 4 -stop-file mysql-bin.011259 -stop-pos 583918266  -big-trx-row-limit 500 -long-trx-seconds 300   -output-dir ./tmpdir

3)、从某一个pos点解析出标准SQL,并且持续打印到屏幕

#伪装成从库解析binlog
./my2sql  -user root -password xxxx -host 127.0.0.1   -port 3306 -mode repl  -work-type 2sql  -start-file mysql-bin.011259  -start-pos 4   -output-toScreen 

五)、应用案例

要使用my2sql解析本地的binlog文件,你需要按照以下步骤操作。假设你已经安装好了my2sql工具,并且你的binlog文件位于本地机器上。

基本命令格式

./my2sql  -user root -password "sz#jKP0mDWdsZ" -host 127.0.0.1   -port 3306  -work-type=2sql -mode=file     -start-file=/data/sort/mysql-bin.000782  -local-binlog-file=/data/sort/mysql-bin.000782
  • -work-type=2sql:表示生成原始SQL语句。
  • -mode=file:表示以离线模式解析binlog文件。
  • -local-binlog-file:指定要解析的binlog文件路径。
    在这里插入图片描述
    在这里插入图片描述

示例

假设你的binlog文件名为mysql-bin.011519,并且存储在/var/lib/mysql/目录下,那么你可以运行如下命令:

my2sql -work-type=2sql -mode=file -local-binlog-file=/var/lib/mysql/mysql-bin.011519

高级选项

根据需求,你可能还需要添加一些额外的参数来定制解析行为,例如:

  • 只解析特定数据库或表
./my2sql  -user root -password "sz#jKP0mDWdsZ" -host 127.0.0.1   -port 3306  -work-type=2sql -mode=file     -start-file=/data/sort/mysql-bin.000782  -local-binlog-file=/data/sort/mysql-bin.000782  -tables=rechecke_zg
  • 将输出结果保存到指定目录

    my2sql -work-type=2sql -mode=file -local-binlog-file=/var/lib/mysql/mysql-bin.011519 -output-dir=/path/to/output/dir
    
  • 为每个表生成一个独立的SQL文件

    my2sql -work-type=2sql -mode=file -local-binlog-file=/var/lib/mysql/mysql-bin.011519 -file-per-table=true
    
  • 将生成的结果打印到屏幕而不是写入文件

    my2sql -work-type=2sql -mode=file -local-binlog-file=/var/lib/mysql/mysql-bin.011519 -output-toScreen=true
    
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐