Ⅰ、背景
早先操作數(shù)據(jù)誤操作后,我們一般通過全量備份+binlog的方式來實(shí)現(xiàn)恢復(fù)(前滾)
有時(shí)只想撤銷一個(gè)幾分鐘前的操作,采用這種方式就會(huì)顯得很笨重
大家都知道Oracle有個(gè)叫做flashback的功能,很遺憾MySQL官方并沒有提供類似的工具
但姜老師的innosql中實(shí)現(xiàn)了這個(gè)功能,而且還兼容官方MySQL,目前支持到5.7版本
Ⅱ、玩兩手
關(guān)注微信公眾號(hào):InsideMySQL,找姜老師要下壓縮包即可,直接解壓,開箱即用,方便快捷
[root@VM_0_5_centos flashback]# ./mysqlbinlog -V
./mysqlbinlog Ver 3.4-InnoSQL for Linux at x86_64
[root@VM_0_5_centos flashback]# ./mysqlbinlog --help |grep flashback
-B, --flashback Flashback data to start_postition or start_datetime.
-E, --fb-event=name only flashback this type of
flashback FALSE
演示閃回功能
(root@localhost) [test]> select version();
+------------+
| version() |
+------------+
| 5.7.20-log |
+------------+
1 row in set (0.08 sec)
(root@localhost) [test]> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
(root@localhost) [test]> select * from flashback;
+------+------+------+------+
| a | b | c | d |
+------+------+------+------+
| 1 | 2 | 3 | 4 |
| 2 | 3 | 4 | 5 |
| 3 | 4 | 5 | 6 |
| 4 | 5 | 6 | 7 |
+------+------+------+------+
4 rows in set (0.00 sec)
(root@localhost) [test]> show master status;
+------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------+----------+--------------+------------------+-------------------+
| bin.000001 | 3028 | | | |
+------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
誤刪數(shù)據(jù)
(root@localhost) [test]> delete from flashback;
Query OK, 4 rows affected (0.01 sec)
(root@localhost) [test]> select * from flashback;
Empty set (0.00 sec)
[root@VM_0_5_centos flashback]# ./mysqlbinlog --base64-output=decode-rows -v bin.000001 --start-position=3028
截取重點(diǎn)部分如下:
### DELETE FROM `test`.`flashback`
### WHERE
### @1=1
### @2=2
### @3=3
### @4=4
### DELETE FROM `test`.`flashback`
### WHERE
### @1=2
### @2=3
### @3=4
### @4=5
### DELETE FROM `test`.`flashback`
### WHERE
### @1=3
### @2=4
### @3=5
### @4=6
### DELETE FROM `test`.`flashback`
### WHERE
### @1=4
### @2=5
### @3=6
### @4=7
可以看到刪除了4條記錄
來看下flashback的核心參數(shù)-B,同樣截取重點(diǎn)
[root@VM_0_5_centos flashback]# ./mysqlbinlog -B --base64-output=decode-rows -v bin.000001 --start-position=3028
### INSERT INTO `test`.`flashback`
### SET
### @1=1
### @2=2
### @3=3
### @4=4
### INSERT INTO `test`.`flashback`
### SET
### @1=2
### @2=3
### @3=4
### @4=5
### INSERT INTO `test`.`flashback`
### SET
### @1=3
### @2=4
### @3=5
### @4=6
### INSERT INTO `test`.`flashback`
### SET
### @1=4
### @2=5
### @3=6
### @4=7
可以看到刪除變成插入了
[root@VM_0_5_centos flashback]# ./mysqlbinlog -B -v bin.000001 --start-position=3028 |mysql -S /tmp/mysql3306.sock
(root@localhost) [test]> select * from flashback;
+------+------+------+------+
| a | b | c | d |
+------+------+------+------+
| 1 | 2 | 3 | 4 |
| 2 | 3 | 4 | 5 |
| 3 | 4 | 5 | 6 |
| 4 | 5 | 6 | 7 |
+------+------+------+------+
4 rows in set (0.00 sec)
恢復(fù)成功
tips:
恢復(fù)的時(shí)候不要加--base64-output=decode-rows,導(dǎo)不進(jìn)去,沒反應(yīng)
Ⅲ、關(guān)于flashback回放的位置點(diǎn)
假設(shè)Master宕機(jī)切到了Slave,Master恢復(fù)后,可能需要將部分?jǐn)?shù)據(jù)Flashback掉(宕機(jī)前最后一部分未傳過去的binlog),F(xiàn)lashback掉的位置很關(guān)鍵,這個(gè)位置一般以Slave上SQL線程最終回放完的位置為準(zhǔn)
Ⅳ、相關(guān)小結(jié)
- flashback是基于binlog的逆操作(邏輯),Oracle的閃回是基于undo做的(物理)
- 使用flashback,binlog_format必須為row,這個(gè)之前binlog章節(jié)有簡單提到過
- binlog_row_image必須設(shè)為full
- flashback僅支持DML操作的閃回,不支持ddl
- 實(shí)例開啟gtid的情況下,不支持flashback
- 同一事務(wù)中的DML語句不僅閃回,語句執(zhí)行順序也會(huì)倒過來(有興趣的可以測試,篇幅原因只貼了一個(gè)delete操作)
tips:
①DDL的閃回功能,商業(yè)版InnoSQL是支持的,修改了MySQL源碼,將刪除的庫或者表保存在回收站(Recycle Bin Tablespace)
②這里我們分析的是出事之后的挽回,那我們最好的辦法就是盡量不要惹事,這里推薦一個(gè)參數(shù)sql_safe_updates,默認(rèn)是off的,開啟此參數(shù),執(zhí)行的sql中存在不帶where條件的delete和update就會(huì)報(bào)錯(cuò)1175
最后祝大家,永遠(yuǎn)不用flashback,一路平安?。?!