MyFlash-DML回滚工具

一、简介

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


三、限制

  1. binlog格式必须为row,且binlog_row_image=full
  2. 仅支持5.6与5.7
  3. 只能回滚DML(增、删、改)



四、使用


    参数:

              

./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*/;

























你可能感兴趣的:(mysql,binlog,恢复,误操作)