(一)MyFlash介紹
MyFlash是美團開發的一個回滾DML操作的工具,該工具是開源的,github地址為:https://github.com/Meituan-Dianping/MyFlash。通過該工具,可以實現MySQL數據庫的閃回。
(二)安裝MyFlash
下載源碼:
git clone https://github.com/Meituan-Dianping/MyFlash.git
安裝依賴包:
yum install -y gcc pkg-config glib2 libgnomeui-devel
編譯:
[root@masterdb MyFlash]# gcc -w `pkg-config --cflags --libs glib-2.0` source/binlogParseGlib.c -o binary/flashback
(三)使用MyFlash
MyFlash語法為:
[root@masterdb binary]# pwd
/root/MyFlash/binary
[root@masterdb 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
語法解析:
- --databaseNames : 需要閃回的數據庫名稱,如果有多個數據庫,用逗號”,”隔開。
- --tableNames : 要閃回的表名稱,如果有多個表,用逗號”,”隔開。
- --start-position :閃回的起始位置,如不指定,從文件開始處回滾。
- --stop-position : 閃回的終止位置,如不指定,回滾到文件結尾。
- --start-datetime : 閃回的開始時間。
- --stop-datetime : 閃回的終止時間。
- --sqlTypes : 指定需要回滾的sql類型,支持INSERT、UPDATE、DELETE,多個類型使用逗號”,”分開。
- --maxSplitSize : 對文件進行固定尺寸的切割,以防止單次應用binlog尺寸較大,對線上造成壓力。
- --binlogFileNames : 指定需要回滾的binlog文件,美團文檔說目前只支持單個binlog文件,經測試已經支持多個binlog文件同時閃回。
- --outBinlogFileNameBase :指定輸出的binlog文件前綴,如不指定,則默認為binlog_output_base.flashback。
- logLevel : 僅供開發者使用,默認級別為error級別。在生產環境中不要修改這個級別,否則輸出過多。
- include-gtids : 指定需要回滾的gtid,支持gtid的單個和范圍兩種形式。
- exclude-gtids : 指定不需要回滾的gtid,用法同include-gtids。
(四)MyFlash測試
(4.1)測試MyFlash閃回功能
STEP1:構造測試數據
[root@masterdb binary]# mysql -uroot -p123456 lijiamandb
mysql> select * from test01; +----+--------+------------+ | id | name | birthday | +----+--------+------------+ | 1 | 小明 | 1993-01-02 | | 2 | 小華 | 1994-08-15 | | 3 | 小麗 | 1995-07-12 | +----+--------+------------+ 3 rows in set (0.00 sec)
STEP2:執行插入、更新、刪除操作
mysql> insert into test01 values(4,'小紅','2000-01-01');
Query OK, 1 row affected (0.01 sec) mysql> delete from test01 where id = 1; Query OK, 1 row affected (0.03 sec) mysql> update test01 set birthday = '1994-09-15'; Query OK, 3 rows affected (0.00 sec) Rows matched: 3 Changed: 3 Warnings: 0 mysql> select * from test01; +----+--------+------------+ | id | name | birthday | +----+--------+------------+ | 2 | 小華 | 1994-09-15 | | 3 | 小麗 | 1994-09-15 | | 4 | 小紅 | 1994-09-15 | +----+--------+------------+ 3 rows in set (0.00 sec)
STEP3:確認上面的DML操作二進制日志
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 | 1079 | | | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
STEP4:發現誤刪除(delete)數據,要求恢復(需要2步)
執行閃回操作,將閃回結果存放到binlog_output_base.flashback中
[root@masterdb binary]# ./flashback --databaseNames=lijiamandb --tableNames=test01 --sqlTypes='DELETE' --binlogFileNames=/mysql/binlog/master-bin.000001
[root@masterdb binary]# ls -lrt total 7320 -rwxr-xr-x 1 root root 7463125 Apr 24 14:03 mysqlbinlog20160408 -rwxr-xr-x 1 root root 54272 Apr 24 14:14 flashback -rw-r--r-- 1 root root 263 Apr 24 14:38 binlog_output_base.flashback
應用閃回的日志:
[root@masterdb binary]# mysqlbinlog binlog_output_base.flashback | mysql -uroot -p123456
STEP5:確認結果,已經將“DELETE”刪除的數據找了回來
mysql> select * from test01;
+----+--------+------------+
| id | name | birthday |
+----+--------+------------+
| 1 | 小明 | 1993-01-02 |
| 2 | 小華 | 1994-09-15 |
| 3 | 小麗 | 1994-09-15 |
| 4 | 小紅 | 1994-09-15 |
+----+--------+------------+
4 rows in set (0.00 sec)
(4.2)測試MyFlash同時應用多個binlog日志閃回
STEP1:確認初始數據
[root@masterdb binary]# mysql -uroot -p123456 lijiamandb
mysql> select * from test01; +----+--------+------------+ | id | name | birthday | +----+--------+------------+ | 1 | 小明 | 1993-01-02 | | 2 | 小華 | 1994-09-15 | | 3 | 小麗 | 1994-09-15 | | 4 | 小紅 | 1994-09-15 | +----+--------+------------+ 4 rows in set (0.00 sec)
STEP2:修改數據,並切換日志
mysql> update test01 set birthday = '1998-01-12' where id = 4;
Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> show master status; +-------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+----------+--------------+------------------+-------------------+ | master-bin.000001 | 1651 | | | | +-------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) mysql> flush logs; Query OK, 0 rows affected (0.01 sec) mysql> show master status; +-------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+----------+--------------+------------------+-------------------+ | master-bin.000002 | 154 | | | | +-------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) mysql> update test01 set name = 'a' where id = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from test01; +----+--------+------------+ | id | name | birthday | +----+--------+------------+ | 1 | 小明 | 1993-01-02 | | 2 | a | 1994-09-15 | | 3 | 小麗 | 1994-09-15 | | 4 | 小紅 | 1998-01-12 | +----+--------+------------+ 4 rows in set (0.00 sec) mysql> flush logs -> ; Query OK, 0 rows affected (0.00 sec) mysql> show master status; +-------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+----------+--------------+------------------+-------------------+ | master-bin.000003 | 154 | | | | +-------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) mysql> update test01 set birthday='2000-12-12' where id = 3; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from test01; +----+--------+------------+ | id | name | birthday | +----+--------+------------+ | 1 | 小明 | 1993-01-02 | | 2 | a | 1994-09-15 | | 3 | 小麗 | 2000-12-12 | | 4 | 小紅 | 1998-01-12 | +----+--------+------------+ 4 rows in set (0.00 sec) mysql> exit Bye
STEP3:執行閃回操作
[root@masterdb binary]# ./flashback --databaseNames=lijiamandb --tableNames=test01 --sqlTypes='UPDATE' --outBinlogFileNameBase=test01_update.flashback --binlogFileNames=/mysql/binlog/master-bin.000001,/mysql/binlog/master-bin.000002,/mysql/binlog/master-bin.000003
[root@masterdb binary]# ls -lrt
total 7332
-rwxr-xr-x 1 root root 7463125 Apr 24 14:03 mysqlbinlog20160408 -rwxr-xr-x 1 root root 54272 Apr 24 14:14 flashback -rw-r--r-- 1 root root 263 Apr 24 14:38 binlog_output_base.flashback -rw-r--r-- 1 root root 495 Apr 24 14:58 test01_update.flashback.flashback.000002 -rw-r--r-- 1 root root 274 Apr 24 14:58 test01_update.flashback.flashback.000001 -rw-r--r-- 1 root root 279 Apr 24 14:58 test01_update.flashback.flashback [root@masterdb binary]# mysqlbinlog test01_update.flashback.flashback test01_update.flashback.flashback.000001 test01_update.flashback.flashback.000002| mysql -uroot -p123456 mysql: [Warning] Using a password on the command line interface can be insecure.
STEP4:確認數據,發現回滾到了最老的數據,不符合要求
[root@masterdb binary]# mysql -uroot -p123456 lijiamandb
mysql> select * from test01; +----+--------+------------+ | id | name | birthday | +----+--------+------------+ | 1 | 小明 | 1993-01-02 | | 2 | 小華 | 1994-08-15 | | 3 | 小麗 | 1995-07-12 | | 4 | 小紅 | 2000-01-01 | +----+--------+------------+ 4 rows in set (0.00 sec)
思路整理:
我們對數據進行多次更新,但是在使用binlog進行閃回的時候,沒有指定開始、結束位置,因此對所有日志都進行了閃回,從而將數據閃回到了最初的數據,不符合我們的要求。如果我們指定合理的開始結束位置,還是可以將數據閃回到任意時刻的。
(五)總結
1.如果binlog日志存在,那么可以使用MyFlash將數據庫閃回到任意時刻。
2.可以對整個實例進行閃回、也可以對某個database,或者是某張表進行閃回,還可以指定某種DML操作進行閃回。
3.MyFlash閃回也有一定的局限性。在閃回時,指定出閃回的開始和結束時間/位置依然是最為重要的,但使用flashback是無法查看二進制日志的,意味着在使用MyFlash時,要么預估開始結束時間,進行不精確的閃回,要么使用mysqlbinlog或binlog2sql來分析日志,得到精確的開始結束時間再閃回。
4.從測試來看,binlog2sql似乎比MyFlash更好用,但是為什么在已經有binlog2sql的基礎上,還要開發MyFlash呢?最主要還是MyFlash性能非常好,閃回速度非常快,美團測試報告中,使用各個工具對約100萬條數據進行閃回的測試如下(原文點這):
【完】
相關文檔集合: 1.MySQL日志--二進制日志(binlog) |