DML误删除恢复
只能恢复DML操作。delete,insert,update。
MySQL server必须设置以下参数:
[mysqld]
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 1G
binlog_format = row
binlog_row_image = full
user需要的最小权限集合:
select, super/replication client, replication slave
建议授权
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO
权限说明
select:需要读取server端information_schema.COLUMNS表,获取表结构的元信息,拼接成可视化的sql语句
super/replication client:两个权限都可以,需要执行'SHOW MASTER STATUS', 获取server端的binlog列表
replication slave:通过BINLOG_DUMP协议获取binlog内容的权限
基本用法
选项
mysql连接配置
-h host; -P port; -u user; -p password
解析模式
--stop-never 持续解析binlog。可选。默认False,同步至执行命令时最新的binlog位置。
-K, --no-primary-key 对INSERT语句去除主键。可选。默认False
-B, --flashback 生成回滚SQL,可解析大文件,不受内存限制。可选。默认False。与stop-never或no-primary-key不能同时添加。
--back-interval -B模式下,每打印一千行回滚SQL,加一句SLEEP多少秒,如不想加SLEEP,请设为0。可选。默认1.0。
解析范围控制
--start-file 起始解析文件,只需文件名,无需全路径 。必须。
--start-position/--start-pos 起始解析位置。可选。默认为start-file的起始位置。
--stop-file/--end-file 终止解析文件。可选。默认为start-file同一个文件。若解析模式为stop-never,此选项失效。
--stop-position/--end-pos 终止解析位置。可选。默认为stop-file的最末位置;若解析模式为stop-never,此选项失效。
--start-datetime 起始解析时间,格式'%Y-%m-%d %H:%M:%S'。可选。默认不过滤。
--stop-datetime 终止解析时间,格式'%Y-%m-%d %H:%M:%S'。可选。默认不过滤。
对象过滤
-d, --databases 只解析目标db的sql,多个库用空格隔开,如-d db1 db2。可选。默认为空。
-t, --tables 只解析目标table的sql,多张表用空格隔开,如-t tbl1 tbl2。可选。默认为空。
--only-dml 只解析dml,忽略ddl。可选。默认False。
--sql-type 只解析指定类型,支持INSERT, UPDATE, DELETE。多个类型用空格隔开,如--sql-type INSERT DELETE。可选。默认为增删改都解析。用了此参数但没填任何类型,则三者都不解析。
对比mysqlbinlog
限制
mysql server必须开启,离线模式下不能解析
参数 binlog_row_image 必须为FULL,暂不支持MINIMAL
解析速度不如mysqlbinlog
优点
纯Python开发,安装与使用都很简单
自带flashback、no-primary-key解析模式,无需再装补丁
flashback模式下,更适合闪回实战
解析为标准SQL,方便理解、筛选
代码容易改造,可以支持更多个性化解析
安装
git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql
cat requirements.txt
pip install -r requirements.txt
yum install python-pip
pip install -r requirements.txt
使用
1.准备测试表
mysql> select * from t1;
+------+---------------------+
| id | time |
+------+---------------------+
| 1 | 2021-02-02 13:41:44 |
| 3 | 2021-02-02 13:41:48 |
| 5 | 2021-02-02 13:41:51 |
| 7 | 2021-02-02 13:41:53 |
| 9 | 2021-02-02 13:41:55 |
| 10 | 2021-02-02 13:41:58 |
| 11 | 2021-02-02 13:42:00 |
| 2 | 2021-02-02 13:42:02 |
| 3 | 2021-02-02 13:42:04 |
| 6 | 2021-02-02 13:42:07 |
| 9 | 2021-02-02 13:42:10 |
| 8 | 2021-02-02 13:42:12 |
+------+---------------------+
delete删除数据
mysql> delete from t1 where id = 3;
Query OK, 2 rows affected (0.00 sec)
update更新数据
mysql> update t1 set id = 3 where id = 10;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
update t1 set id = 3 where id = 11;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
操作完成后的表数据
mysql> select * from t1;
+------+---------------------+
| id | time |
+------+---------------------+
| 1 | 2021-02-02 13:41:44 |
| 5 | 2021-02-02 13:41:51 |
| 7 | 2021-02-02 13:41:53 |
| 3 | 2021-02-02 13:41:58 |
| 3 | 2021-02-02 13:42:00 |
| 2 | 2021-02-02 13:42:02 |
| 6 | 2021-02-02 13:42:07 |
| 8 | 2021-02-02 13:42:12 |
+------+---------------------+
通过binlog2sql来解析binlog日志来恢复数据。
可以看到所有的操作记录。
python binlog2sql.py -h10.128.35.163 -uflash -p123456 -dtest --start-file='mysql.000003'
DELETE FROM `test`.`t1` WHERE `id`=3 AND `time`='2021-02-02 13:41:48' LIMIT 1; #start 259 end 433 time 2021-02-02 13:46:05
DELETE FROM `test`.`t1` WHERE `id`=3 AND `time`='2021-02-02 13:42:04' LIMIT 1; #start 259 end 433 time 2021-02-02 13:46:05
DELETE FROM `test`.`t1` WHERE `id`=9 AND `time`='2021-02-02 13:41:55' LIMIT 1; #start 529 end 703 time 2021-02-02 13:46:27
DELETE FROM `test`.`t1` WHERE `id`=9 AND `time`='2021-02-02 13:42:10' LIMIT 1; #start 529 end 703 time 2021-02-02 13:46:27
UPDATE `test`.`t1` SET `id`=3, `time`='2021-02-02 13:41:58' WHERE `id`=10 AND `time`='2021-02-02 13:41:58' LIMIT 1; #start 799 end 974 time 2021-02-02 13:46:59
UPDATE `test`.`t1` SET `id`=3, `time`='2021-02-02 13:42:00' WHERE `id`=11 AND `time`='2021-02-02 13:42:00' LIMIT 1; #start 1070 end 1245 time 2021-02-02 13:47:29
添加--flashback 生成恢复语句。
python binlog2sql.py --flashback -h10.128.35.163 -uflash -p123456 -dtest --start-file='mysql.000003'
UPDATE `test`.`t1` SET `id`=11, `time`='2021-02-02 13:42:00' WHERE `id`=3 AND `time`='2021-02-02 13:42:00' LIMIT 1; #start 1070 end 1245 time 2021-02-02 13:47:29
UPDATE `test`.`t1` SET `id`=10, `time`='2021-02-02 13:41:58' WHERE `id`=3 AND `time`='2021-02-02 13:41:58' LIMIT 1; #start 799 end 974 time 2021-02-02 13:46:59
INSERT INTO `test`.`t1`(`id`, `time`) VALUES (9, '2021-02-02 13:42:10'); #start 529 end 703 time 2021-02-02 13:46:27
INSERT INTO `test`.`t1`(`id`, `time`) VALUES (9, '2021-02-02 13:41:55'); #start 529 end 703 time 2021-02-02 13:46:27
INSERT INTO `test`.`t1`(`id`, `time`) VALUES (3, '2021-02-02 13:42:04'); #start 259 end 433 time 2021-02-02 13:46:05
INSERT INTO `test`.`t1`(`id`, `time`) VALUES (3, '2021-02-02 13:41:48'); #start 259 end 433 time 2021-02-02 13:46:05
将生成的语句执行。
mysql> UPDATE `test`.`t1` SET `id`=11, `time`='2021-02-02 13:42:00' WHERE `id`=3 AND `time`='2021-02-02 13:42:00' LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> UPDATE `test`.`t1` SET `id`=10, `time`='2021-02-02 13:41:58' WHERE `id`=3 AND `time`='2021-02-02 13:41:58' LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> INSERT INTO `test`.`t1`(`id`, `time`) VALUES (9, '2021-02-02 13:42:10');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `test`.`t1`(`id`, `time`) VALUES (9, '2021-02-02 13:41:55');
INSERT INTO `test`.`t1`(`id`, `time`) VALUES (3, '2021-02-02 13:42:04');
Query OK, 1 row affected (0.02 sec)
mysql> INSERT INTO `test`.`t1`(`id`, `time`) VALUES (3, '2021-02-02 13:42:04');
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO `test`.`t1`(`id`, `time`) VALUES (3, '2021-02-02 13:41:48');
Query OK, 1 row affected (0.01 sec)
插入后,恢复成原始的数据。
mysql> select * from t1;
+------+---------------------+
| id | time |
+------+---------------------+
| 1 | 2021-02-02 13:41:44 |
| 5 | 2021-02-02 13:41:51 |
| 7 | 2021-02-02 13:41:53 |
| 10 | 2021-02-02 13:41:58 |
| 11 | 2021-02-02 13:42:00 |
| 2 | 2021-02-02 13:42:02 |
| 6 | 2021-02-02 13:42:07 |
| 8 | 2021-02-02 13:42:12 |
| 9 | 2021-02-02 13:42:10 |
| 9 | 2021-02-02 13:41:55 |
| 3 | 2021-02-02 13:42:04 |
| 3 | 2021-02-02 13:41:48 |
+------+---------------------+
12 rows in set (0.00 sec)