使用 binlog2sql 闪回 MySQL8 数据
【说明】
MySQL服务器版本 8.0.26
mysql> SELECT version();
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
Python 版本 Python 3.8.10
[infuq ~]# python -V
Python 3.8.10
【安装】
binlog2sql 官方地址
1.安装 binlog2sql
[infuq ~]# git clone https://github.com/danfengcao/binlog2sql.git
[infuq ~]# cd binlog2sql/
[infuq binlog2sql]# ls
LICENSE README.md binlog2sql example requirements.txt tests
2.创建Python虚拟环境
[infuq binlog2sql]# pip install virtualenv
[infuq binlog2sql]# virtualenv -p /usr/bin/python3.8 venv
[infuq binlog2sql]# cd venv/
[infuq venv]# cd bin/
[infuq bin]# source activate # 激活虚拟环境
(venv) [infuq binlog2sql]# ls
LICENSE README.md binlog2sql example requirements.txt tests venv
(venv) [infuq binlog2sql]# pip install -r requirements.txt
(venv) [infuq binlog2sql]# pip list
Package Version
----------------- -------
mysql-replication 0.13
pip 25.0.1
PyMySQL 0.7.11
setuptools 75.3.2
wheel 0.29.0
将 PyMySQL 升级到 0.9.3
(venv) [infuq binlog2sql]# pip install pymysql==0.9.3
(venv) [infuq binlog2sql]# pip list
Package Version
----------------- -------
mysql-replication 0.13
pip 25.0.1
PyMySQL 0.9.3
setuptools 75.3.2
wheel 0.29.0
【试验】
表数据
mysql> SELECT * FROM t1;
+------------+----------+-----------+
| id | t_name | tenant_id |
+------------+----------+-----------+
| 59876754 | Chengdu | 7675365 |
| 59876755 | beijing | 7675365 |
| 59876756 | nanchang | 7675365 |
| 1021219158 | Zhaoxin | 7254309 |
+------------+----------+-----------+# 删除
mysql> DELETE FROM t1 WHERE id=59876754 OR id = 59876755;
恢复数据操作
mysql> SHOW MASTER LOGS;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000003 | 5166 | No |
| binlog.000004 | 200 | No |
| binlog.000005 | 200 | No |
| binlog.000006 | 200 | No |
| binlog.000007 | 179 | No |
| binlog.000008 | 512 | No |
| binlog.000009 | 200 | No |
| binlog.000010 | 1089 | No |
| binlog.000011 | 156 | No |
+---------------+-----------+-----------+
先根据误操作大概时间过滤数据, 找到 position
需要逐个查看每个 BINLOG 文件
(venv) [infuq binlog2sql]# python binlog2sql/binlog2sql.py -h192.168.10.12 -P3306 -uroot -p'9527' -ddb0 -tt1 --start-file='binlog.000003' --stop-file='binlog.000003' --start-datetime='2025-04-26 14:20:00' --stop-datetime='2025-04-26 15:46:00' --sql-type DELETE
...
(venv) [infuq binlog2sql]# python binlog2sql/binlog2sql.py -h192.168.10.12 -P3306 -uroot -p'9527' -ddb0 -tt1 --start-file='binlog.000011' --stop-file='binlog.000011' --start-datetime='2025-04-26 14:20:00' --stop-datetime='2025-04-26 15:46:00' --sql-type DELETE
输出:
DELETE FROM `db0`.`t1` WHERE `id`=59876754 AND `t_name`='Chengdu' AND `tenant_id`=7675365 LIMIT 1; #start 4 end 442 time 2025-04-26 15:45:32
DELETE FROM `db0`.`t1` WHERE `id`=59876755 AND `t_name`='beijing' AND `tenant_id`=7675365 LIMIT 1; #start 4 end 442 time 2025-04-26 15:45:32
找到了 position, start-position=4, stop-position=442
生成回滚SQL
(venv) [infuq binlog2sql]# python binlog2sql/binlog2sql.py -h192.168.10.12 -P3306 -uroot -p'9527' -ddb0 -tt1 --start-file='binlog.000011' --stop-file='binlog.000011' --start-position=4 --stop-position=442 --sql-type DELETE -B
输出:
INSERT INTO `db0`.`t1`(`id`, `t_name`, `tenant_id`) VALUES (59876755, 'beijing', 7675365); #start 4 end 442 time 2025-04-26 15:45:32
INSERT INTO `db0`.`t1`(`id`, `t_name`, `tenant_id`) VALUES (59876754, 'Chengdu', 7675365); #start 4 end 442 time 2025-04-26 15:45:32
由于逐个查看每个 BINLOG 文件比较繁琐,因此自己写了一个脚本文件 flashback.py ,可以快速自动查看每个 BINLOG 文件里是否有删除语句.
(venv) [infuq binlog2sql]# ls
LICENSE README.md binlog2sql example flashback.py requirements.txt tests venv
flashback.py 文件内容如下
#! /usr/bin/env pythonimport os
import pymysqldef handle():# 查看在 2025-04-26 14:20:00 到 2025-04-26 15:46:00 时间范围, 在表 t1 上被执行的删除语句host = "192.168.10.12"port = 3306user = "root"passwd = "9527"db = "db0"table = "t1"start_time = "2025-04-26 14:20:00"stop_time = "2025-04-26 15:46:00"conn = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db)cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)sql = "show master logs"cursor.execute(sql)all_data = cursor.fetchall()for data in all_data:binlog_name = data['Log_name']command = "python binlog2sql/binlog2sql.py \-h%s \-P%s \-u%s \-p'%s' \-d%s \-t%s \--start-file='%s' \--stop-file='%s' \--start-datetime='%s' \--stop-datetime='%s' \--sql-type DELETE"print('scan', binlog_name)command = command % (host,port,user,passwd,db,table,binlog_name,binlog_name,start_time,stop_time)res = os.popen(command).read()if res:rows = res.split('\n')for row in rows:print(row)conn.close()cursor.close()if __name__ == '__main__':handle()
执行 flashback.py
(venv) [infuq binlog2sql]# python flashback.py
scan binlog.000003
scan binlog.000004
scan binlog.000005
scan binlog.000006
scan binlog.000007
scan binlog.000008
scan binlog.000009
scan binlog.000010
scan binlog.000011
DELETE FROM `db0`.`t1` WHERE `id`=59876754 AND `t_name`='Chengdu' AND `tenant_id`=7675365 LIMIT 1; #start 4 end 442 time 2025-04-26 15:45:32
DELETE FROM `db0`.`t1` WHERE `id`=59876755 AND `t_name`='beijing' AND `tenant_id`=7675365 LIMIT 1; #start 4 end 442 time 2025-04-26 15:45:32