MySQL数据误删flashback

使用binlog2sql(Python版)

解析binlog文件来创建回滚的sql

准备工作

需要提前安装Python环境

git clone https://github.com/danfengcao/binlog2sql.git
cd binlog2sql
pip3 install -r requirements.txt

MySQL必须 开启binlog,且binlog_format=ROW,且binlog_row_image=FULL

show variables like 'log_bin';
show variables like '%binlog_format%';
show variables like '%binlog_row_image%';

具体使用

解析出标准SQL

python3 binlog2sql.py -hip -P3310 -ubinlog2sql -p'pwd1' -d testdb -t t --start-file='mysql-bin.000004' --only-dml

仅解析testdb库的t表,只解析dml,忽略ddl,结果中也会包含格式为statement的日志

INSERT INTO `testdb`.`t`(`id`, `c`, `d`) VALUES (0, 0, 0); #start 4 end 438 time 2022-12-15 13:52:48
INSERT INTO `testdb`.`t`(`id`, `c`, `d`) VALUES (5, 5, 5); #start 4 end 438 time 2022-12-15 13:52:48
INSERT INTO `testdb`.`t`(`id`, `c`, `d`) VALUES (10, 10, 10); #start 4 end 438 time 2022-12-15 13:52:48
DELETE FROM `testdb`.`t` WHERE `id`=0 AND `c`=0 AND `d`=0 LIMIT 1; #start 469 end 737 time 2022-12-15 13:53:03
DELETE FROM `testdb`.`t` WHERE `id`=5 AND `c`=5 AND `d`=5 LIMIT 1; #start 469 end 737 time 2022-12-15 13:53:03

解析出回滚SQL

python3 binlog2sql.py --flashback -hip -P3310 -ubinlog2sql -p'pwd1' -d testdb -t t --start-file='mysql-bin.000001' --only-dml
  • 添加--only-dml参数,结果会过滤格式为statement的日志
  • 不添加--only-dml参数,格式为statement的日志原样输出
INSERT INTO `testdb`.`t`(`id`, `c`, `d`) VALUES (0, 0, 0); #start 4 end 438 time 2022-12-15 13:52:48
INSERT INTO `testdb`.`t`(`id`, `c`, `d`) VALUES (5, 5, 5); #start 4 end 438 time 2022-12-15 13:52:48
INSERT INTO `testdb`.`t`(`id`, `c`, `d`) VALUES (10, 10, 10); #start 4 end 438 time 2022-12-15 13:52:48
DELETE FROM `testdb`.`t` WHERE `id`=0 AND `c`=0 AND `d`=0 LIMIT 1; #start 469 end 737 time 2022-12-15 13:53:03
DELETE FROM `testdb`.`t` WHERE `id`=5 AND `c`=5 AND `d`=5 LIMIT 1; #start 469 end 737 time 2022-12-15 13:53:03
INSERT INTO `testdb`.`t`(`id`, `c`, `d`) VALUES (60, 60, 60); #start 19012 end 19267 time 2022-12-15 14:21:46
DELETE FROM `testdb`.`t` WHERE `id`=60 AND `c`=60 AND `d`=60 LIMIT 1; #start 19298 end 19553 time 2022-12-15 14:22:18

出现的问题

Traceback (most recent call last):
  File "binlog2sql/binlog2sql.py", line 149, in <module>
    back_interval=args.back_interval, only_dml=args.only_dml, sql_type=args.sql_type)
  File "binlog2sql/binlog2sql.py", line 46, in __init__
    self.connection = pymysql.connect(**self.conn_setting)
  File "/usr/local/lib/python3.6/site-packages/pymysql/__init__.py", line 90, in Connect
    return Connection(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 706, in __init__
    self.connect()
  File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 931, in connect
    self._get_server_information()
  File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 1269, in _get_server_information
    self.server_charset = charset_by_id(lang).name
  File "/usr/local/lib/python3.6/site-packages/pymysql/charset.py", line 38, in by_id
    return self._by_id[id]
KeyError: 255

升级PyMySQL

pip3 install --upgrade PyMySQL

Traceback (most recent call last):
  File "binlog2sql/binlog2sql.py", line 7, in <module>
    from pymysqlreplication import BinLogStreamReader
  File "/usr/local/lib/python3.6/site-packages/pymysqlreplication/__init__.py", line 23, in <module>
    from .binlogstream import BinLogStreamReader
  File "/usr/local/lib/python3.6/site-packages/pymysqlreplication/binlogstream.py", line 8, in <module>
    from pymysql.util import int2byte
ModuleNotFoundError: No module named 'pymysql.util'

解决方案

pip3 uninstall pymysql
pip3 install pymysql==0.9.3

binlog中没有记录新的日志

原因:账号权限不对
解决:创建账号,重新授权

CREATE USER 'binlog2sql'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd1';
GRANT SELECT,REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'binlog2sql'@'%';
flush privileges;

参考

binlog2sql github地址

使用binlog2sql(Java版)

<dependency>
  <groupId>com.github.shyiko</groupId>
  <artifactId>mysql-binlog-connector-java</artifactId>
  <version>0.18.0</version>
</dependency>

仅能监听新的binlog,不能解析一个文件的所有event

参考

binlog2sql_java github地址

使用美团MyFlash

该方式不像 binlog2sql 一样转换binlog为易读的sql语句,而是直接截取复制并修改二进制 binlog 文件实现SQL的反转,然后使用mysqlbinlog 命令读取新生成的二进制binlog闪回文件,将闪回操作导入数据库实现数据的恢复。

git clone https://github.com/Meituan-Dianping/MyFlash.git
gcc -w `pkg-config --cflags --libs glib-2.0` source/binlogParseGlib.c -o binary/flashback

获取开始和结束位置

show binlog events in 'mysql-bin.000001';

获取要闪回事务的开始和结束位置

生成闪回binlog文件

这里使用的是docker的mysql,需要将docker内部的binlog文件拷贝出来

docker cp xxx:/var/lib/mysql/mysql-bin.000001 . 

binlogFileNames指定binlog文件的具体路径

rm -rf MyFlash-master/binlog_output_base.flashback
MyFlash-master//binary/flashback --binlogFileNames=mysql-bin.000001 --sqlTypes=delete --start-position=21247 --stop-position=21552

通过开始和结束位置来具体确定一个事务(删除 tb_user 中 uid 为7的行)

执行闪回

将生成的闪回文件拷贝到docker内部

docker cp binlog_output_base.flashback xxx:/

在docker内部执行此命令

mysqlbinlog --skip-gtids  binlog_output_base.flashback | mysql -uroot -p
select * from tb_user;

可以看到结果中uid为7的行已经加回来了

参考

[美团] Myflash 的安装使用
MyFlash——美团点评的开源MySQL闪回工具
MyFlash-github地址

posted @ 2023-09-11 21:05  strongmore  阅读(67)  评论(0编辑  收藏  举报