DBA或開發人員,有時會誤刪或者誤更新數據,如果是線上環境并且影響較大,就需要能快速回滾。傳統恢復方法是利用備份重搭實例,再應用去除錯誤sql后的binlog來恢復數據。此法費時費力,甚至需要停機維護,并不適合快速回滾。也有團隊利用LVM快照來縮短恢復時間,但快照的缺點是會影響mysql的性能。
MySQL閃回(flashback)利用binlog直接進行回滾,能快速恢復且不用停機。本文將介紹閃回原理,給出筆者的實戰經驗,并對現存的閃回工具作比較。
開胃菜
某天,小明因種種原因,誤刪了大批線上用戶表的數據。他急忙找到公司DBA請求幫助,“客服電話已被打爆,大量用戶投訴無法登陸,領導非常惱火。請問多久能恢復數據?”DBA一臉懵逼,沉默十秒后,伸出一根手指。“你的意思是一分鐘就能恢復?太好了。”小明終于有些放松,露出了一絲笑容。“不,我們中有個人將會離開公司。”DBA沉痛的說道。
勿讓悲劇發生,盡早將此文轉給公司DBA。
閃回原理
binlog概述
MySQL binlog以event的形式,記錄了MySQL server從啟用binlog以來所有的變更信息,能夠幫助重現這之間的所有變化。MySQL引入binlog主要有兩個目的:一是為了主從復制;二是某些備份還原操作后需要重新應用binlog。
有三種可選的binlog格式,各有優缺點:
利用binlog閃回,需要將binlog格式設置為row。row模式下,一條使用innodb的insert會產生如下格式的binlog:
| # at 1129#161225 23:15:38 server id 3773306082 end_log_pos 1197 Query thread_id=1903021 exec_time=0 error_code=0SET TIMESTAMP=1482678938/*!*/;BEGIN/*!*/;# at 1197#161225 23:15:38 server id 3773306082 end_log_pos 1245 Table_map: `test`.`user` mapped to number 290# at 1245#161225 23:15:38 server id 3773306082 end_log_pos 1352 Write_rows: table id 290 flags: STMT_END_FBINLOG 'muJfWBPiFOjgMAAAAN0EAAAAACIBAAAAAAEABHRlc3QABHVzZXIAAwMPEQMeAAACmuJfWB7iFOjgawAAAEgFAAAAACIBAAAAAAEAAgAD//gBAAAABuWwj+i1tVhK1hH4AgAAAAblsI/pkrFYStYg+AMAAAAG5bCP5a2ZWE/onPgEAAAABuWwj+adjlhNeAD4BQAAAAJ0dFhRYJM='/*!*/;# at 1352#161225 23:15:38 server id 3773306082 end_log_pos 1379 Xid = 5327954COMMIT/*!*/; | 
閃回原理
既然binlog以event形式記錄了所有的變更信息,那么我們把需要回滾的event,從后往前回滾回去即可。
對于單個event的回滾,我們以表test.user來演示原理
| mysql> show create table test.user/G*************************** 1. row *************************** Table: userCreate Table: CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 |