myflash數(shù)據(jù)閃回工具使用說明

前言

使用數(shù)據(jù)庫過程中難免有出錯的時候,假如不小心刪除了一張表,或者錯誤執(zhí)行了update語句,那么這個時候想要恢復數(shù)據(jù)就需要用到數(shù)據(jù)閃回工具,如:binlog2sql和myflash等。但因為binlog2sql工具要求數(shù)據(jù)庫在線,即需要連接數(shù)據(jù)庫進行binlog解析才能轉換為sql,無法直接對binlog文件進行解析,使用條件上相對苛刻,所以沒有考慮。

介紹

myflash是美團研發(fā)的一款開源的數(shù)據(jù)庫閃回工具,他可以用來回滾DML操作。

使用條件

  • MySQL數(shù)據(jù)庫必須開啟binlog
  • binlog格式必須為row,且binlog_row_image=full
  • 僅支持5.6與5.7
  • 只能回滾DML(增、刪、改)

下載與安裝

下載地址為:https://github.com/Meituan-Dianping/MyFlash
按照下圖方式下載,可以不用安裝git。

下載myflash.png

首先要安裝編譯所必須的依賴包

[root@hadoop101 /]# yum install -y gcc pkg-config glib2 libgnomeui-devel

將壓縮包上傳到服務器后使用unzip命令解壓。

[root@hadoop101 package]# pwd
/opt/package
[root@hadoop101 package]# ls
myflash-master.zip  mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz
[root@hadoop101 package]# unzip -d /opt/ myflash-master.zip
...解壓文件列表過長不展示
[root@hadoop101 MyFlash-master]# cd /opt/MyFlash-master/
[root@hadoop101 MyFlash-master]# ls
binary  binlog_output_base.flashback  build.sh  doc  License.md  README.md  source  testbinlog

如果下載的是zip包,他會有一個編譯好的程序為解壓路徑/binary/flashback,也可以再次編譯,進入解壓后的目錄,編譯并安裝

[root@hadoop101 MyFlash-master]# gcc -w  `pkg-config --cflags --libs glib-2.0` source/binlogParseGlib.c  -o binary/flashback

安裝完之后是沒有環(huán)境變量的,只能使用絕對路徑調用工具,使用--help可以查看命令的使用方式

[root@hadoop101 binary]# /opt/MyFlash-master/binary/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

參數(shù)解釋,這里我直接借用了別人的,有些東西我也沒用過,所以不確保是否可用。

參數(shù) 釋義
--databaseNames 需要閃回的數(shù)據(jù)庫名稱,如果有多個數(shù)據(jù)庫,用逗號”,”隔開。
--tableNames 要閃回的表名稱,如果有多個表,用逗號”,”隔開。
--start-position 閃回的起始位置,如不指定,從文件開始處回滾。
--stop-position 閃回的終止位置,如不指定,回滾到文件結尾。
--start-datetime 閃回的開始時間。
--stop-datetime 閃回的終止時間。
--sqlTypes 指定需要回滾的sql類型,支持INSERT、UPDATE、DELETE,多個類型使用逗號”,”分開。
--maxSplitSize 對文件進行固定尺寸的切割,以防止單次應用binlog尺寸較大,對線上造成壓力。
--binlogFileNames 指定需要回滾的binlog文件,美團文檔說目前只支持單個binlog文件,經(jīng)測試已經(jīng)支持多個binlog文件同時閃回。
--outBinlogFileNameBase 指定輸出的binlog文件前綴,如不指定,則默認為binlog_output_base.flashback。
logLevel 僅供開發(fā)者使用,默認級別為error級別。在生產(chǎn)環(huán)境中不要修改這個級別,否則輸出過多。
include-gtids 指定需要回滾的gtid,支持gtid的單個和范圍兩種形式。
exclude-gtids 指定不需要回滾的gtid,用法同include-gtids。

事先準備

首先我準備了一個單節(jié)點的mysql,然后刷新了binlog,之后會建表寫入演示數(shù)據(jù),然后模擬誤操作再演示回滾數(shù)據(jù)。

mysql> flush logs; 
Query OK, 0 rows affected (0.02 sec)
mysql> show master status ;
+------------------+----------+--------------+------------------+--------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                          |
+------------------+----------+--------------+------------------+--------------------------------------------+
| mysql-bin.000005 |      194 |              |                  | 2ec63aca-cd00-11ec-ba97-000c29648fd7:1-144 |
+------------------+----------+--------------+------------------+--------------------------------------------+
1 row in set (0.00 sec)

mysql> create database demo;
Query OK, 1 row affected (0.00 sec)
mysql> create table `time`(
    -> `id` int primary key auto_increment,
    -> `string` varchar(50),
    -> `create_time` datetime
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into demo.`time` values(null,'!@#',now());
Query OK, 1 row affected (0.01 sec)
mysql> insert into demo.`time` values(null,'*&^',now());      
Query OK, 1 row affected (0.00 sec)
mysql> insert into demo.`time` values(null,'^%$',now());   
Query OK, 1 row affected (0.00 sec)

mysql> select * from demo.`time`;
+----+--------+---------------------+
| id | string | create_time         |
+----+--------+---------------------+
|  1 | !@#    | 2022-05-06 17:21:48 |
|  2 | *&^    | 2022-05-06 17:21:53 |
|  3 | ^%$    | 2022-05-06 17:21:58 |
+----+--------+---------------------+
3 rows in set (0.00 sec)

刪除數(shù)據(jù)

此時刪除整張表的數(shù)據(jù),但保留表結構,一般誤操作都是在圖形化界面誤操作的,所以我這里使用navicat模擬刪除。


刪除數(shù)據(jù).png
這里千萬不要點刪除表或者截斷表,刪除表的命令的drop,截斷表的命令是truncate,這兩個都是DDL語句,binlog是不會記錄詳細的刪除信息的,一旦執(zhí)行操作將無法回滾,是myflash無法拯救的。

此時可以查看一下mysql的binlog文件,看看binlog的情況。

[root@hadoop101 binlog]# pwd
/data/mysql_data/binlog
[root@hadoop101 binlog]# ls
mysql-bin.000001  mysql-bin.000002  mysql-bin.000003  mysql-bin.000004  mysql-bin.000005  mysql-bin.index
[root@hadoop101 binlog]# /opt/mysql_6033/bin/mysqlbinlog -vv --base64-output=DECODE-ROWS mysql-bin.000005
......
create database demo
/*!*/;
# at 353
......
create table `time`( `id` int primary key auto_increment, `string` varchar(50), `create_time` datetime )
/*!*/;
# at 596
......
# at 865
#220506 17:21:48 server id 1000  end_log_pos 914 CRC32 0x305f5f15       Write_rows: table id 112 flags: STMT_END_F
### INSERT INTO `demo`.`time`
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2='!@#' /* VARSTRING(200) meta=200 nullable=1 is_null=0 */
###   @3='2022-05-06 17:21:48' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
# at 914
......
# at 1214
#220506 17:21:53 server id 1000  end_log_pos 1263 CRC32 0x834574e8      Write_rows: table id 112 flags: STMT_END_F
### INSERT INTO `demo`.`time`
### SET
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2='*&^' /* VARSTRING(200) meta=200 nullable=1 is_null=0 */
###   @3='2022-05-06 17:21:53' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
......
# at 1563
#220506 17:21:58 server id 1000  end_log_pos 1612 CRC32 0xa58ebd4d      Write_rows: table id 112 flags: STMT_END_F
### INSERT INTO `demo`.`time`
### SET
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2='^%$' /* VARSTRING(200) meta=200 nullable=1 is_null=0 */
###   @3='2022-05-06 17:21:58' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
......
#220506 17:22:24 server id 1000  end_log_pos 1951 CRC32 0xc374eb11      Delete_rows: table id 112 flags: STMT_END_F
### DELETE FROM `demo`.`time`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2='!@#' /* VARSTRING(200) meta=200 nullable=1 is_null=0 */
###   @3='2022-05-06 17:21:48' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
### DELETE FROM `demo`.`time`
### WHERE
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2='*&^' /* VARSTRING(200) meta=200 nullable=1 is_null=0 */
###   @3='2022-05-06 17:21:53' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
### DELETE FROM `demo`.`time`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2='^%$' /* VARSTRING(200) meta=200 nullable=1 is_null=0 */
###   @3='2022-05-06 17:21:58' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
# at 1951
......

多余的內容我用省略號代替了,主要是想展示在binlog中包含了所有有價值的內容,比如建表,insert和delete,而且對整張表執(zhí)行delete命令時,他會一條一條數(shù)據(jù)刪除,刪除的每條數(shù)據(jù)都完好的保存在binlog中,這也為回滾提供了便捷。

回滾

使用myfalsh工具對binlog進行回滾,他會生成一個新的以.flashback為后綴的文件,這是一個已經(jīng)回滾完的binlog文件,上面binlog中的delete語句會被轉換為insert語句,然后使用mysqlbinlog命令就可以導入此文件到mysql實例中,如此便完成回滾。
執(zhí)行命令:

[root@hadoop101 binlog]# /opt/MyFlash-master/binary/flashback --databaseNames="demo" --tableNames="time" --start-datetime="2022-05-06 17:00:00" --stop-datetime="2022-05-06 18:00:00" --sqlTypes="UPDATE,DELETE" --binlogFileNames=/data/mysql_data/binlog/mysql-bin.000005 --outBinlogFileNameBase=/tmp/rollbak.sql

命令中要回滾的數(shù)據(jù)庫為demo,要回滾的表是time,誤操作的開始時間,即回滾開始時間為2022-05-06 17:00:00,回滾結束時間為2022-05-06 18:00:00,要回滾的語句指定為UPDATE和DELETE,要解析的binlog文件是mysql-bin.000005,回滾后的文件保存在/tmp/下,文件名前綴為rollbak.sql。如果有多個數(shù)據(jù)庫和多張表記得用逗號隔開。
然后會在/tmp/路徑下生成一個叫rollbak.sql.flashback的文件,該文件使用mysqlbinlog命令解析后如下圖

回滾后的binlog.png

最后將此文件導入即可:

[root@hadoop101 binlog]# /opt/mysql_6033/bin/mysqlbinlog --skip-gtids /tmp/rollbak.sql.flashback | /opt/mysql_6033/bin/mysql -h 127.0.0.1 -P 6033 -u root -p
這里注意,如果mysql數(shù)據(jù)庫使用了gtid,則導入回滾數(shù)據(jù)時要添加--skip-gtids的參數(shù),否則會報錯。

最后登錄數(shù)據(jù)庫查看


查看回滾結果.png

額外的內容

insert和delete的回滾很容易,兩者的操作是相悖的,只需要直接替換關鍵詞即可,而update是特殊的,在某些場景下不建議在--sqlTypes參數(shù)中添加UPDATE。
比如原字段A的值是1,現(xiàn)將其改為99,那么在binlog中會記錄下“update table set A=99 where A=1”,如果將其回滾,這條語句就會變成“update table set A=1 where A=99”,而如果在誤操作delete之間有正常的update,那么回滾之后數(shù)據(jù)就會異常,正常應該執(zhí)行的update語句被回滾回去了。
所以一定要清楚自己的誤操作到底操作了什么,針對誤操作的類型進行單獨的回滾是比較好的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容