MyFlash是由美团点评公司技术工程部开发维护的一个回滚DML操作的工具。该工具通过解析v4版本的binlog,完成回滚操作。相对已有的回滚工具,其增加了更多的过滤选项,让回滚更加容易
项目地址:https://github.com/Meituan-Dianping/MyFlash
二、安装
安装环境:centos7 64位
cd /usr/local
git clone https://github.com/Meituan-Dianping/MyFlash.git
cd MyFlash
#动态编译:
gcc -w `pkg-config --cflags --libs glib-2.0` source/binlogParseGlib.c -o binary/flashback
三、限制
四、使用
参数:
./flashback --help
Usage:
flashback [OPTION...]
Help Options:
-h, --help Show help options
Application Options:
--databaseNames databaseName to apply. if multiple, seperate by comma(,)
--tableNames tableName to apply. if multiple, seperate by comma(,)
--start-position start position
--stop-position stop position
--start-datetime start time (format %Y-%m-%d %H:%M:%S)
--stop-datetime stop time (format %Y-%m-%d %H:%M:%S)
--sqlTypes sql type to filter . support INSERT, UPDATE ,DELETE. if multiple, seperate by comma(,)
--maxSplitSize max file size after split, the uint is M
--binlogFileNames binlog files to process. if multiple, seperate by comma(,)
--outBinlogFileNameBase output binlog file name base
--logLevel log level, available option is debug,warning,error
--include-gtids gtids to process
--exclude-gtids gtids to skip
下面的这些参数是可以任意组合的。
1.databaseNames
指定需要回滚的数据库名。多个数据库可以用“,”隔开。如果不指定该参数,相当于指定了所有数据库。
2.tableNames
指定需要回滚的表名。多个表可以用“,”隔开。如果不指定该参数,相当于指定了所有表。
3.start-position
指定回滚开始的位置。如不指定,从文件的开始处回滚。请指定正确的有效的位置,否则无法回滚
4.stop-position
指定回滚结束的位置。如不指定,回滚到文件结尾。请指定正确的有效的位置,否则无法回滚
5.start-datetime
指定回滚的开始时间。注意格式必须是 %Y-%m-%d %H:%M:%S。 如不指定,则不限定时间
6.stop-datetime
指定回滚的结束时间。注意格式必须是 %Y-%m-%d %H:%M:%S。 如不指定,则不限定时间
7.sqlTypes
指定需要回滚的sql类型。目前支持的过滤类型是INSERT, UPDATE ,DELETE。多个类型可以用“,”隔开。
8.maxSplitSize
一旦指定该参数,对文件进行固定尺寸的分割(单位为M),过滤条件有效,但不进行回滚操作。该参数主要用来将大的binlog文件切割,防止单次应用的binlog尺寸过大,对线上造成压力
9.binlogFileNames
指定需要回滚的binlog文件,目前只支持单个文件,后续会增加多个文件支持
10.outBinlogFileNameBase
指定输出的binlog文件前缀,如不指定,则默认为binlog_output_base.flashback
11.logLevel
仅供开发者使用,默认级别为error级别。在生产环境中不要修改这个级别,否则输出过多
12.include-gtids
指定需要回滚的gtid,支持gtid的单个和范围两种形式。
13.exclude-gtids
指定不需要回滚的gtid,用法同include-gtids
回滚测试:
表结构:
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`tel` varchar(16) NOT NULL DEFAULT '15800377643' COMMENT '手机号',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=8000001 DEFAULT CHARSET=utf8
1 row in set (0.01 sec)
mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 7279195 |
+----------+
1 row in set (2.46 sec)
mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 201 |
| mysql-bin.000002 | 201 |
| mysql-bin.000003 | 201 |
| mysql-bin.000004 | 131034361 |
| mysql-bin.000005 | 201 |
| mysql-bin.000006 | 201 |
| mysql-bin.000007 | 480 |
| mysql-bin.000008 | 35610031 |
+------------------+-----------+
8 rows in set (0.00 sec)
误删除测试:
mysql> flush logs;
Query OK, 0 rows affected (0.02 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from t1 where id>3000000;
Query OK, 4919909 rows affected (5 min 0.48 sec) #测试机器配置烂啊没办法
mysql> commit;
Query OK, 0 rows affected (0.39 sec)
mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 201 |
| mysql-bin.000002 | 201 |
| mysql-bin.000003 | 201 |
| mysql-bin.000004 | 131034361 |
| mysql-bin.000005 | 201 |
| mysql-bin.000006 | 201 |
| mysql-bin.000007 | 480 |
| mysql-bin.000008 | 35610078 |
| mysql-bin.000009 | 93879160 |
+------------------+-----------+
9 rows in set (0.01 sec)
#开始恢复被delete的数据
[root@wangxin binary]# time ./flashback --binlogFileNames=/data/mysql/3306/logs/mysql-bin.000009 --sqlTypes=DELETE
real 0m0.738s
user 0m0.286s
sys 0m0.440s
[root@wangxin binary]# du -sh *
90M binlog_output_base.flashback
48K flashback
6.6M mysqlbinlog20160408
将delete转换成insert的速度超级快啊,有木有。
由于binlog_output_base.flashback有90M所以需要将其进行切片,让导入到mysql的速度更加快
./flashback --maxSplitSize=20 --binlogFileNames=binlog_output_base.flashback
[root@wangxin binary]# ll
total 190776
-rw-r--r-- 1 root root 20977983 Nov 23 15:48 binlog_output_base.000001
-rw-r--r-- 1 root root 20977983 Nov 23 15:48 binlog_output_base.000002
-rw-r--r-- 1 root root 20977983 Nov 23 15:48 binlog_output_base.000003
-rw-r--r-- 1 root root 20977983 Nov 23 15:48 binlog_output_base.000004
-rw-r--r-- 1 root root 10585292 Nov 23 15:48 binlog_output_base.000005
-rw-r--r-- 1 root root 93878918 Nov 23 15:46 binlog_output_base.flashback
-rwxr-xr-x 1 root root 48888 Nov 17 13:59 flashback
-rwxr-xr-x 1 root root 7463125 Nov 17 13:56 mysqlbinlog20160408
#分别将1 2 3 4 5导入数据库:
[root@wangxin binary]# mysqlbinlog binlog_output_base.000001 |mysql --login-path=wangxin
ERROR 1782 (HY000) at line 17: @@SESSION.GTID_NEXT cannot be set to ANONYMOUS when @@GLOBAL.GTID_MODE = ON.
出现了报错。由于文件里面的GTID值在binlog里面已经存在了,所以需要关闭主库的GTID
或者使用--skip-gtids参数
1、mysqlbinlog --skip-gtids binlog_output_base.000001 |mysql --login-path=wangxin
2、
mysql> set global GTID_MODE = ON_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)
mysql> set global GTID_MODE = OFF_PERMISSIVE;
Query OK, 0 rows affected (0.00 sec)
mysql> set global GTID_MODE = OFF;
Query OK, 0 rows affected (0.00 sec)
#现在再来导入:
mysqlbinlog binlog_output_base.000001 |mysql --login-path=wangxin
mysqlbinlog binlog_output_base.000002 |mysql --login-path=wangxin
mysqlbinlog binlog_output_base.000003 |mysql --login-path=wangxin
mysqlbinlog binlog_output_base.000004 |mysql --login-path=wangxin
mysqlbinlog binlog_output_base.000005 |mysql --login-path=wangxin
#将主库GTID重新开启
mysql> set global GTID_MODE = OFF_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)
mysql> set global GTID_MODE = ON_PERMISSIVE;
Query OK, 0 rows affected (0.00 sec)
mysql> set global GTID_MODE = ON;
Query OK, 0 rows affected (0.01 sec)
#验证数据量:
mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 7279195 |
+----------+
1 row in set (2.53 sec)
误更新测试:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update t1 set name='mic' where id > 5000000;
Query OK, 2934501 rows affected (2 min 43.44 sec)
Rows matched: 2934501 Changed: 2934501 Warnings: 0
mysql> commit;
Query OK, 0 rows affected (0.49 sec)
./flashback --binlogFileNames=/data/mysql/3306/logs/mysql-bin.000017 --sqlTypes=UPDATE
#转换成sql文件看看内容
mysqlbinlog -v -v --base64-output=decode-rows binlog_output_base.flashback >17.sql
#171123 16:26:29 server id 13306 end_log_pos 117898077 CRC32 0x5a4c3e9e Update_rows: table id 223 flags: STMT_END_F
### UPDATE `wangxin`.`t1`
### WHERE
### @1=5000001 /* INT meta=0 nullable=0 is_null=0 */
### @2='mic' /* VARSTRING(96) meta=96 nullable=0 is_null=0 */
### @3='15800377643' /* VARSTRING(48) meta=48 nullable=0 is_null=0 */
### SET
### @1=5000001 /* INT meta=0 nullable=0 is_null=0 */
### @2='1' /* VARSTRING(96) meta=96 nullable=0 is_null=0 */
### @3='15800377643' /* VARSTRING(48) meta=48 nullable=0 is_null=0 */
之后的步骤和上面一样就不演示了,还有insert操作,会转变为delete
insert操作回滚:
mysql> show create table a\G
*************************** 1. row ***************************
Table: a
Create Table: CREATE TABLE `a` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> select * from a;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into a values(4);
Query OK, 1 row affected (0.01 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
./flashback --binlogFileNames=/data/mysql/3306/logs/mysql-bin.000019 --sqlTypes=INSERT
#查看19.sql 可以看到已经转变成delete sql了
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#171123 16:44:49 server id 13306 end_log_pos 123 CRC32 0xf0b4e58c Start: binlog v 4, server v 5.7.17-log created 171123 16:44:49
# Warning: this binlog is either in use or was not closed properly.
# at 123
#171123 16:45:30 server id 13306 end_log_pos 170 CRC32 0xbdcd839e Table_map: `wangxin`.`a` mapped to number 221
# at 170
#171123 16:45:30 server id 13306 end_log_pos 210 CRC32 0xc265d3ea Delete_rows: table id 221 flags: STMT_END_F
### DELETE FROM `wangxin`.`a`
### WHERE
### @1=4 /* INT meta=0 nullable=1 is_null=0 */
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;