使用 binlog2sql 闪回 MySQL8 数据

【说明】

MySQL服务器版本 8.0.26

bash 复制代码
mysql> SELECT version();
+-----------+
| version() |
+-----------+
| 8.0.26    |
+-----------+

Python 版本 Python 3.8.10

bash 复制代码
[infuq ~]# python -V
Python 3.8.10

【安装】

binlog2sql 官方地址

1.安装 binlog2sql

bash 复制代码
[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虚拟环境

bash 复制代码
[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      # 激活虚拟环境
bash 复制代码
(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

bash 复制代码
(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

【试验】

表数据

sql 复制代码
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;

恢复数据操作

bash 复制代码
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 文件

bash 复制代码
(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

bash 复制代码
(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 文件里是否有删除语句.

bash 复制代码
(venv) [infuq binlog2sql]# ls
LICENSE  README.md  binlog2sql  example  flashback.py  requirements.txt  tests  venv

flashback.py 文件内容如下

python 复制代码
#! /usr/bin/env python

import os
import pymysql

def handle():
    # 查看在 2025-04-26 14:20:00 到 2025-04-26 15:46:00 时间范围, 在表 t1 上被执行的删除语句
    host = "192.168.10.12"
    port = 3306
    user = "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

bash 复制代码
(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
相关推荐
kfepiza4 小时前
Debian-10编译安装Mysql-5.7.44 笔记250706
linux·数据库·笔记·mysql·debian·bash
不剪发的Tony老师4 小时前
phpMyAdmin:一款经典的MySQL在线管理工具又回来了
数据库·mysql·phpmyadmin
张璐月7 小时前
mysql的性能优化:组提交、数据页复用、全表扫描优化、刷脏页
数据库·mysql·性能优化
渣渣盟8 小时前
Flink数据流高效写入MySQL实战
mysql·flink·scala
NF禾凡8 小时前
【Mysql作业】
数据库·mysql
Kay_Liang9 小时前
MySQL SQL语句精要:DDL、DML与DCL的深度探究
开发语言·数据库·sql·mysql·database
诺亚凹凸曼11 小时前
一条mysql的查询语句是怎样执行的?
数据库·mysql
程序猿小D11 小时前
[附源码+数据库+毕业论文+答辩PPT+部署教程+配套软件]基于SpringBoot+MyBatis+MySQL+Maven+Vue实现的交流互动管理系统
spring boot·mysql·vue·mybatis·毕业论文·答辩ppt·交流互动
刺客xs13 小时前
MYSQL数据库----DCL语句
android·数据库·mysql
胖墩的IT13 小时前
在高并发场景下,仅依赖数据库机制(如行锁、版本控制)无法完全避免数据异常的问题
数据库·mysql