先講個事,前段時間,系統長時間不用的一個功能被開放出來了,想當然的我沒有在測試平台上測試,直接操作了正式系統(的確是我不嚴謹),導致好多數據異常,頁面展示錯亂了。於是我想到的第一個就是進行備份還原。項目進行了7天的備份,每天凌晨自動備份,但是凌晨到現在的數據就會丟失了,這可是重大問題啊。我頓時慌了,於是只能尋求DBA的幫助。這邊省略五百字。。。
最后問題解決了,讓我對數據恢復產生了興趣,聽DBA講用的方法是Flashback閃回工具,也簡單,於是我也自學了一下,這邊做個介紹。
flashback可以把數據庫恢復到以前某個時間點(或者說某個binlog的某個pos)。比如忘了帶where條件的update、delete操作,傳統的恢復方式是利用全備+二進制日志前滾進行恢復,相比於傳統的全備+增備,flashback顯然更為快速、簡單。這里有個注意點,DDL語句是不支持進行flashback的,謹慎操作。
先講講所謂的閃回是什么意思,了解他的原理是什么。
其實很簡單,相當於回滾,MySQL的binlog以event的形式,記錄了MySQL中所有的變更情況,利用binlog我們就能夠重現所記錄的所有操作。flashback工具(-B 參數)可對rows格式的binlog可以進行逆向操作,將已執行的delete語句反向生成insert語句,將update語句生成反向update語句,將insert語句反向生成delete語句。這里提一句,binlog是有三種格式的:
- statement,基於SQL語句的模式,一般來說生成的binlog尺寸較小,但是某些不確定性SQL語句或函數在復制過程可能導致數據不一致甚至出錯;
- row,基於數據行的模式,記錄的是數據行的完整變化。相對更安全,推薦使用(但通常生成的binlog會比其他兩種模式大很多);
- mixed,混合模式,可以根據情況自動選用statement抑或row模式;這個模式下也可能造成主從數據不一致。它屬於MySQL 5.1版本時期的過渡方案,已不推薦使用了。
注意:使用mysqlbinlog flashback 工具必須設置:binlog_format = row。如果誤操作的事務是由多個event組成的,那么必須將整個事務倒序恢復,即從最后一個event恢復到第一個event。
使用方法:
第一步:安裝flashback
MySQL本身是不自帶flashback的,我們需要進行自己安裝。下載地址:https://pan.baidu.com/s/1U33OO79RjBMJPSi0dDpKdg
將mysqlbinlog文件移至mysql安裝路徑的bin目錄下,執行mysqlbinlog --help(自行解決報錯),無任何報錯后再執行mysqlbinlog -V,看是否mysql是否版本發生了變化,且多了一個 -B 參數,這樣就裝完了。
第二步:測試效果
隨便建一張表,比如叫frame_ou
create table frame_ou(
ouguid varchar(50) not null,
ouname varchar(20),
oulevel int(5)
)
我們往里面插入一條數據,insert into frame_ou values('111','組織部',1);
看下binlog里面,可以看到這句插入語句mysqlbinlog -vv mysql-bin.000004
1 ### INSERT INTO `test`.`frame_ou` 2 ### SET 3 ### @ouguid=111 /* VARSTRING(50) meta=50 nullable=0 is_null=0 */ 4 ### @ouname='組織部' /* VARSTRING(50) meta=20 nullable=1 is_null=0 */ 5 ### @oulevel=1 /* SHORTINT meta=0 nullable=1 is_null=0 */
然后執行下flashback mysqlbinlog -vv mysql-bin.000004 -B,然后就會發現
### DELETE FROM `test`.`frame_ou` ### WHERE ### @ouguid=111 /* VARSTRING(50) meta=50 nullable=0 is_null=0 */ ### @ouname='組織部' /* VARSTRING(50) meta=20 nullable=1 is_null=0 */ ### @oulevel=1 /* SHORTINT meta=0 nullable=1 is_null=0 */
同理,delete操作將會被轉換為insert,update被轉換為反向的update;若在一個事務中既有insert、update、delete語句,通過使用-B參數后,不僅三種DML語句完成了逆向轉換,並且語句順序也會發生顛倒。
在binlog中找到誤操作的pos變化區間后,使用mysqlbinlog -B 恢復:
# mysqlbinlog -B --start-position=431 --stop-position=509 mysql-bin.000004 | mysql -uroot -p
注意事項:
1) binlog_format=row
2) 只支持insert、update、delete
3) 不支持drop 、truncate、alter等DDL語句