概述
在生产环境中经常会遇到误删除、改错数据的情况,现在介绍一款很方便、又省时的MySQL闪回工具binlog2sql,它可以实现数据的快速回滚,从binlog中提取SQL,并能生成回滚SQL语句。binlog以event作为单位记录数据库变更的数据信息,闪回就是可以重现这些变化数据信息之前的操作。也就是说,对于insert操作,会生成delete吾句,反之delete操作会生成insert吾句。对于update操作,也会生成相反的update语句。这款工具只能在binlog格式为row模式下才能使用。
安装必需的工具包
安装准备各种依赖的工具包
python-pip PyMYSQL python-mysql-replication wheel argparse
tar -xzf pip-9.0.1.tar.gz
cd pip-9.0.1
python setup.py install
tar -xzf PyMySQL-0.7.11.tar.gz
cd PyMySQL-0.7.11
python setup.py install
tar -xzf mysql-replication-0.13.tar.gz
cd mysql-replication-0.13
python setup.py install
tar -xzf wheel-0.29.0.tar.gz
cd wheel-0.29.0
python setup.py install
tar -xzf argparse-1.4.0.tar.gz
cd argparse-1.4.0
安装binlog2sql工具
binlog2sql闪回工具下载地址:
https://github.com/danfengcao/binlog2sql
安装binlog2sql工具:
unzip binlog2sql-master.zip
cd binlog2sql-master
pip install -r requirements.txt
查看binlog2sql命令解释
python binlog2sql.py --help
可通过python binlog2sql.py -help命令查看参数的使用方式。
-B,--flashback:生成回滚语句。
--start-file:需要解析的binlog文件。
--start-position:解析 binlog 的起始位置。
--stop-position:解析 binlog 的结束位置。
--start-datetime:从哪个时间点的binlog开始解析,格式必须为datetime。
--stop-datetime:到哪个时间点的binlog停止解析,格式必须为datetime。
-d,--databases:只输出目标 db 的 SQL。
-t,--tables:只输出目标 tables 的 SQL。
binlog2sql的注意事项:
(1) 要保证MySQL服务是开启的,离线无法进行分析binlog。
(2) binlog_format 必须是 row 格式。
(3) DDL语句无法做到闪回,只能解析DML语句。
闪回测试步骤
(1) 创建用户,用于闪回
grant select,replication slave,replication client on *.* to 'flashback'@'%' identified by 'XXXXX';
flush privileges;
(2) 创建测试表并准备数据
use test;
CREATE TABLE TEST_FLASHBACK
(EMPNO INT(10),
ENAME VARCHAR(10),
JOB VARCHAR(9),
MGR INT(10),
HIREDATE DATETIME,
SAL INT(10),
COMM INT(10),
DEPTNO INT(10));
INSERT INTO TEST_FLASHBACK VALUES (7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO TEST_FLASHBACK VALUES (7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO TEST_FLASHBACK VALUES (7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
(3) 删除数据
delete from TEST_FLASHBACK;
(4) 闪回数据
show master status;
python binlog2sql.py -h192.168.0.13 -P3306 -uflashback -pXXXXX -dtest -tTEST_FLASHBACK --start-file='mysql-bin.000005' --start-datetime='2020-02-22 15:40:00' --stop-datetime='2020-02-22 15:50:00'
python binlog2sql.py -h192.168.0.13 -P3306 -uflashback -pXXXXX -dtest -tTEST_FLASHBACK --start-file='mysql-bin.000005' --start-position=1845 --stop-position=2201 -B > TEST_FLASHBACK_ROLLBACK.sql
闪回测试记录
[root@source mysql]# mysql -p
root@db 15:40: [(none)]> grant select,replication slave,replication client on *.* to 'flashback'@'%' identified by 'XXXXX';
Query OK, 0 rows affected, 1 warning (0.01 sec)
root@db 15:42: [(none)]> flush privileges;
Query OK, 0 rows affected (0.02 sec)
root@db 15:42: [(none)]> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 622 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
root@db 15:42: [(none)]> use test;
Database changed
root@db 15:43: [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| BONUS |
| DEPT |
| EMP |
| SALGRADE |
+----------------+
4 rows in set (0.00 sec)
root@db 15:43: [test]> CREATE TABLE TEST_FLASHBACK
-> (EMPNO INT(10),
-> ENAME VARCHAR(10),
-> JOB VARCHAR(9),
-> MGR INT(10),
-> HIREDATE DATETIME,
-> SAL INT(10),
-> COMM INT(10),
-> DEPTNO INT(10));
Query OK, 0 rows affected (0.58 sec)
root@db 15:44: [test]> INSERT INTO TEST_FLASHBACK VALUES (7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
Query OK, 1 row affected (0.02 sec)
root@db 15:44: [test]> INSERT INTO TEST_FLASHBACK VALUES (7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
Query OK, 1 row affected (0.02 sec)
root@db 15:44: [test]> INSERT INTO TEST_FLASHBACK VALUES (7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
Query OK, 1 row affected (0.00 sec)
root@db 15:44: [test]> SELECT * FROM TEST_FLASHBACK;
+-------+-------+----------+------+---------------------+------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+----------+------+---------------------+------+------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00 | 800 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 00:00:00 | 1600 | 300 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 00:00:00 | 1250 | 500 | 30 |
+-------+-------+----------+------+---------------------+------+------+--------+
3 rows in set (0.00 sec)
root@db 15:44: [test]> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 1845 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
root@db 15:45: [test]> delete from TEST_FLASHBACK;
Query OK, 3 rows affected (0.00 sec)
root@db 15:45: [test]> select * from TEST_FLASHBACK;
Empty set (0.00 sec)
root@db 15:45: [test]> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 2232 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@source binlog2sql]# python binlog2sql.py -h192.168.0.13 -P3306 -uflashback -pXXXXX -dtest -tTEST_FLASHBACK --start-file='mysql-bin.000005' --start-datetime='2020-02-22 15:40:00' --stop-datetime='2020-02-22 15:50:00'
[root@source binlog2sql]# python binlog2sql.py -h192.168.0.13 -P3306 -uflashback -pXXXXX -dtest -tTEST_FLASHBACK --start-file='mysql-bin.000005' --start-position=1845 --stop-position=2201 -B > TEST_FLASHBACK_ROLLBACK.sql
[root@source binlog2sql]# ll
total 40
-rwxr-xr-x 1 root root 7747 Oct 12 2018 binlog2sql.py
-rwxr-xr-x 1 root root 11581 Oct 12 2018 binlog2sql_util.py
-rw-r--r-- 1 root root 10616 Feb 22 16:40 binlog2sql_util.pyc
-rw-r--r-- 1 root root 92 Oct 12 2018 __init__.py
-rw-r--r-- 1 root root 689 Feb 22 17:06 TEST_FLASHBACK_ROLLBACK.sql
[root@source binlog2sql]# more TEST_FLASHBACK_ROLLBACK.sql
INSERT INTO `test`.`TEST_FLASHBACK`(`ENAME`, `SAL`, `EMPNO`, `MGR`, `JOB`, `COMM`, `HIREDATE`, `DEPTNO`) VALUES ('WARD', 1250, 7521, 7698, 'SALESMAN', 500, '1981-02-22 00:00:00', 30);
INSERT INTO `test`.`TEST_FLASHBACK`(`ENAME`, `SAL`, `EMPNO`, `MGR`, `JOB`, `COMM`, `HIREDATE`, `DEPTNO`) VALUES ('ALLEN', 1600, 7499, 7698, 'SALESMAN', 300, '1981-02-20 00:00:00', 30);
INSERT INTO `test`.`TEST_FLASHBACK`(`ENAME`, `SAL`, `EMPNO`, `MGR`, `JOB`, `COMM`, `HIREDATE`, `DEPTNO`) VALUES ('SMITH', 800, 7369, 7902, 'CLERK', NULL, '1980-12-17 00:00:00', 20);
root@db 17:08: [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| BONUS |
| DEPT |
| EMP |
| SALGRADE |
| TEST_FLASHBACK |
+----------------+
5 rows in set (0.00 sec)
root@db 17:08: [test]> select * from TEST_FLASHBACK;
Empty set (0.00 sec)
root@db 17:08: [test]> system pwd
/opt/soft/binlog2sql-master/binlog2sql
root@db 17:08: [test]> source /opt/soft/binlog2sql-master/binlog2sql/TEST_FLASHBACK_ROLLBACK.sql
root@db 17:08: [test]> select * from TEST_FLASHBACK;
+-------+-------+----------+------+---------------------+------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+----------+------+---------------------+------+------+--------+
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 00:00:00 | 1250 | 500 | 30 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 00:00:00 | 1600 | 300 | 30 |
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00 | 800 | NULL | 20 |
+-------+-------+----------+------+---------------------+------+------+--------+
3 rows in set (0.00 sec)