在 MySQL
数据库的日常运维中,误删数据、误更新、人为操作失误等事故时有发生。一旦发生这类问题,如何快速、准确地恢复数据,是每个
DBA 和开发人员必须掌握的核心技能。而 binlog(二进制日志) 正是实现这类数据恢复的关键工具。
binlog 是 MySQL 用来记录所有数据变更操作的日志文件,包括:
INSERT
UPDATE
DELETE
注意:SELECT 不会写入 binlog。
场景 | 说明 |
---|---|
误删整张表 | DELETE FROM table 或 DROP TABLE |
误更新数据 | UPDATE table SET col = 'wrong_value' WHERE ... |
误插入错误数据 | INSERT INTO table VALUES(...) |
事务回滚失败 | 事务未正确回滚,导致数据异常 |
条件 | 说明 |
---|---|
binlog_format=ROW |
推荐使用,记录行级变更,适合恢复 |
binlog_row_image=FULL |
记录完整行数据,便于还原 |
expire_logs_days 设置合理 |
确保 binlog 未被自动清理 |
binlog 文件未被 PURGE | 文件必须存在,才能解析 |
有恢复工具支持 | 如 binlog2sql 、my2sql 、mysqlbinlog |
配置项 | 推荐值 | 对恢复的影响 |
---|---|---|
binlog_format |
ROW |
推荐,记录行级变化,恢复更准确 |
binlog_row_image |
FULL |
推荐,记录完整行数据,便于还原 |
binlog_rows_query_log_events |
ON |
可选,记录原始 SQL,便于定位问题 |
expire_logs_days |
7 ~14 |
推荐,避免日志被清理,影响恢复 |
sync_binlog |
1 |
推荐,每次提交都刷盘,避免数据丢失 |
binlog_do_db / binlog_ignore_db |
按需配置 | 控制记录哪些库,避免无关日志干扰 |
你执行了如下 SQL,误删了用户表中的部分数据:
DELETE FROM users WHERE create_time < '2025-07-01';
现在需要恢复这部分数据。
使用 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 0x12345678
DELETE 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.git
cd binlog2sql
pip 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');
导入恢复文件:
mysql -u root -p your_database < rollback.sql
binlog 是 MySQL 数据恢复的“最后一道防线”,通过合理配置 + 高效工具(如 binlog2sql),你可以轻松实现 误删、误更新的精准还原,保障数据安全与业务连续性。
工具 | 用途 | 命令示例 |
---|---|---|
mysqlbinlog |
解析 binlog 文件 | mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001 |
binlog2sql |
生成回滚 SQL | python binlog2sql.py --start-file=mysql-bin.000001 --only-types='DELETE' |
my2sql |
支持多种恢复模式 | my2sql -logFile=mysql-bin.000001 -sqlTypes="DELETE" -workType recoverBinlog |