【MySQL】MySQL Binlog 日志恢复实战指南:从误删到精准还原
在 MySQL
数据库的日常运维中,误删数据、误更新、人为操作失误等事故时有发生。一旦发生这类问题,如何快速、准确地恢复数据,是每个
DBA 和开发人员必须掌握的核心技能。而 binlog(二进制日志) 正是实现这类数据恢复的关键工具。
🧠 一、什么是 binlog?为什么它能用于数据恢复?
✅ binlog 是什么?
binlog 是 MySQL 用来记录所有数据变更操作的日志文件,包括:
INSERT
UPDATE
DELETE
📌 注意:SELECT 不会写入 binlog。
✅ binlog 的作用:
- 主从复制(Replication)
- 数据恢复(Recovery)
- 审计追踪(Audit)
- CDC(Change Data Capture)
🔍 二、binlog 数据恢复的常见场景
DELETE FROM table
或 DROP TABLE
UPDATE table SET col = \'wrong_value\' WHERE ...
INSERT INTO table VALUES(...)
🛠 三、binlog 恢复的必备条件
binlog_format=ROW
binlog_row_image=FULL
expire_logs_days
设置合理binlog2sql
、my2sql
、mysqlbinlog
📊 四、不同 binlog 配置对恢复的影响对比表
binlog_format
ROW
binlog_row_image
FULL
binlog_rows_query_log_events
ON
expire_logs_days
7
~14
sync_binlog
1
binlog_do_db
/ binlog_ignore_db
🧪 五、实战:使用 binlog 恢复误删数据
🧩 场景描述:
你执行了如下 SQL,误删了用户表中的部分数据:
DELETE FROM users WHERE create_time < \'2025-07-01\';
现在需要恢复这部分数据。
🧰 步骤一:确认 binlog 文件和位置
使用 SHOW BINARY LOGS
查看当前 binlog 文件列表:
SHOW BINARY LOGS;
输出示例:
+------------------+-----------+| Log_name | File_size |+------------------+-----------+| mysql-bin.000001 | 104857600 || mysql-bin.000002 | 104857600 || mysql-bin.000003 | 104857600 |+------------------+-----------+
或者:查看 /etc/my.cnf 配置文件,查看binlog位置
cat /etc/my.cnf
找到对应内容:
#binlog日志log_bin=/mydata/binlog/mysql-bin
查看目录下内容
[root@localhost binlog]# ll /mydata/binlog总用量 4466040-rw-r-----. 1 mysql mysql 1073746300 7月 17 19:32 mysql-bin.002000-rw-r-----. 1 mysql mysql 1080852579 7月 19 20:11 mysql-bin.002001-rw-r-----. 1 mysql mysql 1073744846 7月 22 16:30 mysql-bin.002002-rw-r-----. 1 mysql mysql 835637107 7月 24 17:32 mysql-bin.002003-rw-r-----. 1 mysql mysql 376266572 7月 25 10:54 mysql-bin.002004-rw-r-----. 1 mysql mysql 160 7月 24 17:32 mysql-bin.index
🧰 步骤二:使用 mysqlbinlog
解析 binlog 文件
# 提取所有mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000002 > binlog_parsed.sql# 提取指定位置范围的内容mysqlbinlog --start-position=123 --stop-position=456 mysql-bin.000001 -v > partial_output.sql# 提取指定时间范围的内容mysqlbinlog -v --start-datetime=\"2025-07-25 10:00:00\" --stop-datetime=\"2025-07-25 12:00:00\" mysql-bin.000001 > output_readable.sql
-base64-output=DECODE-ROWS
:将 ROW 格式解码为可读 SQLv
:显示详细信息
🔍 小提示
-
如果你想让输出更清晰,可以加两个
v
参数:mysqlbinlog -vv mysql-bin.000001 > output.sq
这样会显示列名而不是
@1
,@2
。但仅限于MySQL > 8.0 且binlog_row_metadata
参数为FULL
🧰 步骤三:查找误删操作的时间点或位置
使用 grep
查找 DELETE 操作:
grep -A 20 \"DELETE FROM users\" binlog_parsed.sql
输出示例:
# at 123456#250724 10:00:00 server id 100 end_log_pos 123456 CRC32 0x12345678DELETE FROM users WHERE create_time < \'2025-07-01\'
记录 start
和 end
位置,如:
start_pos = 123400
end_pos = 123500
🧰 步骤四:使用 binlog2sql
生成回滚语句(推荐)
安装 binlog2sql
:
git clone https://github.com/danfengcao/binlog2sql.gitcd binlog2sqlpip install -r requirements.txt
执行恢复命令:
python binlog2sql.py --host=127.0.0.1 --port=3306 \\ --user=root --password=your_password \\ --start-file=mysql-bin.000002 \\ --start-pos=123400 \\ --end-pos=123500 \\ --only-types=\'DELETE\' \\ --output=rollback.sql
生成的 rollback.sql
文件内容如下:
INSERT INTO users VALUES (1, \'Tom\', \'2024-01-01\');INSERT INTO users VALUES (2, \'Jerry\', \'2024-02-01\');...
若不想使用 binlog2sql
,也可以手动组装恢复sql语句
解析出的日志中提取旧值(即删除前的数据),然后手工编写 INSERT 语句。
示例:
# 提取的原始DELETE 语句# at 377308574#250725 10:59:45 server id 100 end_log_pos 377308676 CRC32 0xc88b5091 Delete_rows: table id 18120 flags: STMT_END_F### DELETE FROM `test1`### WHERE### @1=\'1\' /* VARSTRING(300) meta=300 nullable=0 is_null=0 */### @2=\'张三\' /* VARSTRING(300) meta=300 nullable=1 is_null=0 */### @3=\'111\' /* VARSTRING(300) meta=300 nullable=1 is_null=0 */# 手动转换为INSERT 语句INSERT INTO test1(id, name, phone)VALUES (1, \'张三\', \'111\');
🧰 步骤五:执行恢复 SQL
导入恢复文件:
mysql -u root -p your_database < rollback.sql
📌 六、一句话总结
binlog 是 MySQL 数据恢复的“最后一道防线”,通过合理配置 + 高效工具(如 binlog2sql),你可以轻松实现 误删、误更新的精准还原,保障数据安全与业务连续性。
📚 七、推荐工具与命令汇总
mysqlbinlog
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001
binlog2sql
python binlog2sql.py --start-file=mysql-bin.000001 --only-types=\'DELETE\'
my2sql
my2sql -logFile=mysql-bin.000001 -sqlTypes=\"DELETE\" -workType recoverBinlog