基本上每個跟資料庫打交道的程式設計師(當然也可能是你同事)都會碰乙個問題,mysql誤操作後如何快速回滾?比如,delete一張表,忘加限制條件,整張表沒了。假如這還是線上環境核心業務資料,那這事就鬧大了。誤操作後,能快速回滾資料是非常重要的。
binlog2sql快速回滾
首先,確認你的mysql server開啟了binlog,設定了以下引數:
[mysqld] server-id = 1 log_bin = /var/log/mysql/mysql-bin.log max_binlog_size = 1000m binlog-format = row
如果沒有開啟binlog,也沒有預先生成回滾sql,那真的無法快速回滾了。對存放重要業務資料的mysql,強烈建議開啟binlog。
隨後,安裝開源工具binlog2sql。binlog2sql是一款簡單易用的binlog解析工具,其中乙個功能就是生成回滾sql。
git clone pip install -r requirements.txt
然後,我們就可以生成回滾sql了。
背景:誤刪了test庫f表整張表的資料,需要緊急回滾。
原有資料
mysql> select * from f; +-----+-----+---------------------+ | uid | did | updatetime | +-----+-----+---------------------+ | 1 | 18 | 2016-12-06 12:28:18 | | 2 | 19 | 2016-12-06 12:55:56 | | 3 | 20 | 2016-12-07 14:00:58 | | 4 | 21 | 2016-12-07 14:01:00 | +-----+-----+---------------------+ 誤操作mysql> delete from f;query ok, 4 rows affected (0.00 sec) f表被清空 mysql> select * from f; empty set (0.00 sec)
回滾步驟:
登入mysql,檢視目前的binlog檔案
mysql> show master logs; +------------------+-----------+ | log_name | file_size | +------------------+-----------+ | mysql-bin.000001 | 12262268 | | mysql-bin.000002 | 132776 | +------------------+-----------+
最新的binlog檔案是mysql-bin.000002,我們再定位誤操作sql的binlog位置
$ python binlog2sql/binlog2sql.py -h127.0.0.1 -p3306 -uadmin -p'admin' -dtest -t f --start-file='mysql-bin.000002'
輸出:
delete from `test`.`f` where `did`=18 and `updatetime`='2016-12-06 12:28:18' and `uid`=1 limit 1; #start 4 end 314 delete from `test`.`f` where `did`=19 and `updatetime`='2016-12-06 12:55:56' and `uid`=2 limit 1; #start 4 end 314 delete from `test`.`f` where `did`=20 and `updatetime`='2016-12-07 14:00:58' and `uid`=3 limit 1; #start 4 end 314 delete from `test`.`f` where `did`=21 and `updatetime`='2016-12-07 14:01:00' and `uid`=4 limit 1; #start 4 end 314
生成回滾sql,並檢查回滾sql是否正確
$ python binlog2sql/binlog2sql.py -h127.0.0.1 -p3306 -uadmin -p'admin' -dtest -t f --start-file='mysql-bin.000002' --start-pos=4 --end-pos=314 -b
輸出:
insert into `test`.`f`(`did`, `updatetime`, `uid`) values (21, '2016-12-07 14:01:00', 4); #start 4 end 314 insert into `test`.`f`(`did`, `updatetime`, `uid`) values (20, '2016-12-07 14:00:58', 3); #start 4 end 314 insert into `test`.`f`(`did`, `updatetime`, `uid`) values (19, '2016-12-06 12:55:56', 2); #start 4 end 314 insert into `test`.`f`(`did`, `updatetime`, `uid`) values (18, '2016-12-06 12:28:18', 1); #start 4 end 314
確認回滾sql正確,執行回滾語句。登入mysql,資料回滾成功。
$ python binlog2sql.py -h127.0.0.1 -p3306 -uadmin -p'admin' -dtest -t f --start-file='mysql-bin.000002' --start-pos=4 --end-pos=314 -b | mysql -h127.0.0.1 -p3306 -uadmin -p'admin' mysql> select * from f; +-----+-----+---------------------+ | uid | did | updatetime | +-----+-----+---------------------+ | 1 | 18 | 2016-12-06 12:28:18 | | 2 | 19 | 2016-12-06 12:55:56 | | 3 | 20 | 2016-12-07 14:00:58 | | 4 | 21 | 2016-12-07 14:01:00 | +-----+-----+---------------------+
至此,不用再擔心被炒魷魚了。
常見問題
有人會問,我ddl誤操作了怎麼快速回滾?比如drop了一張大表。
很難做到。因為即使在在row模式下,ddl操作也不會把每行資料的變化記錄到binlog,所以ddl無法通過binlog回滾。實現ddl回滾,必須要在執行ddl前先備份老資料。確實有人通過修改mysql server原始碼實現了ddl的快速回滾,我找到阿里的xiaobin lin提交了乙個patch。但據我所知,國內很少有網際網路公司應用了這個特性。原因的話,我認為最主要還是懶的去折騰,沒必要搞這個低頻功能,次要原因是會增加一些額外儲存。
所以,ddl誤操作的話一般只能通過備份來恢復。如果公司連備份也不能用了,那真的建議去買張飛機票了。幹啥?跑唄
mysql除了binlog2sql,是否還有其他回滾工具?
當然有。阿里彭立勛對mysqlbinlog增加了flashback的特性,這應該是mysql最早有的flashback功能,彭解決的是dml的回滾,並說明了利用binlog進行dml閃回的設計思路。ddl回滾特性也是由阿里團隊提出並實現的。這兩個功能是有創新精神的,此後出現的閃回工具基本都是對上面兩者的模仿。另外,去哪兒開源的inception是一套mysql自動化運維工具,這個就比較重了,支援dml回滾,還不是從binlog回滾的,是從備份回滾的,也支援ddl回滾表結構,資料是回滾不了滴~
摘自:
mysql回滾命令 關於MySQL回滾機制
在事務中,每個正確的原子操作都會被順序執行,直到遇到錯誤的原子操作,此時事務會將之前的操作進行回滾。回滾的意思是如果之前是插入操作,那麼會執行刪 除插入的記錄,如果之前是update操作,也會執行update操作將之前的記錄還原 因此,正確的原子操作是真正被執行過的。是物理執行。在當前事務中確實能看...
mysql恢復和回滾資料
資料庫不小心刪除或者表不小心刪除,通過mysql恢復的話需要確保刪除前是mysql是開啟binlog。具體步驟 1.查詢binlog狀態以及位置。在 etc my.cfg檢視binlog開啟狀態 可以看到binlog開始狀態是開啟的。2.mysql查詢執行的binlog檔案。目標檔案是mysql b...
關於回滾,mysql
假如銀行中轉帳的時候,如果乙個地方的錢已經發出去了,而另外乙個地方突然停最,那麼這樣就會造成一種情況就是轉帳失敗了,那到怎麼處理這種情況了呢,做乙個簡單的刪除兩個表中的內容來說乙個 conn new mysqli localhost username 123 mydata conn query se...