MySQL誤操做後如何快速恢復數據

基本上每一個跟數據庫打交道的程序員(固然也多是你同事)都會碰一個問題,MySQL誤操做後如何快速回滾?好比,delete一張表,忘加限制條件,整張表都沒了。假如這仍是線上環境核心業務數據,那這事就鬧大了。誤操做後,能快速回滾數據是很是重要的。php

傳統解法

用全量備份重搭實例,再利用增量binlog備份,恢復到誤操做以前的狀態。而後跳過誤操做的SQL,再繼續應用binlog。此法費時費力,不值得再推薦。html

binlog2sql快速回滾

首先,確認你的MySQL server開啓了binlog,設置瞭如下參數:python

[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 1000M
binlog-format = row

若是沒有開啓binlog,也沒有預先生成回滾SQL,那真的沒法快速回滾了。對存放重要業務數據的MySQL,強烈建議開啓binlog。mysql

隨後,安裝開源工具binlog2sql。binlog2sql是一款簡單易用的binlog解析工具,其中一個功能就是生成回滾SQL。git

git clone https://github.com/danfengcao/binlog2sql.git
pip install -r requirements.txt

而後,咱們就能夠生成回滾SQL了。程序員

背景:誤刪了test庫tbl表整張表的數據,須要緊急回滾。github

test庫tbl表原有數據
mysql> select * from tbl;
+----+--------+---------------------+
| id | name   | addtime             |
+----+--------+---------------------+
|  1 | 小趙   | 2016-12-10 00:04:33 |
|  2 | 小錢   | 2016-12-10 00:04:48 |
|  3 | 小孫   | 2016-12-10 00:04:51 |
|  4 | 小李   | 2016-12-10 00:04:56 |
+----+--------+---------------------+
4 rows in set (0.00 sec)

mysql> delete from tbl;
Query OK, 4 rows affected (0.00 sec)

tbl表被清空
mysql> select * from tbl;
Empty set (0.00 sec)

恢復數據步驟sql

  1. 登陸mysql,查看目前的binlog文件數據庫

    mysql> show master logs;
    +------------------+-----------+
    | Log_name         | File_size |
    +------------------+-----------+
    | mysql-bin.000046 |  12262268 |
    | mysql-bin.000047 |      3583 |
    +------------------+-----------+
  2. 最新的binlog文件是mysql-bin.000047,咱們再定位誤操做SQL的binlog位置bash

    $ python binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttbl --start-file='mysql-bin.000047'
    輸出:
    DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-10 00:04:33' AND `id`=1 AND `name`='小趙' LIMIT 1; #start 3346 end 3556
    DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-10 00:04:48' AND `id`=2 AND `name`='小錢' LIMIT 1; #start 3346 end 3556
    DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-10 00:04:51' AND `id`=3 AND `name`='小孫' LIMIT 1; #start 3346 end 3556
    DELETE FROM `test`.`tbl` WHERE `addtime`='2016-12-10 00:04:56' AND `id`=4 AND `name`='小李' LIMIT 1; #start 3346 end 3556
  3. 生成回滾sql,並檢查回滾sql是否正確

    $ python binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttbl --start-file='mysql-bin.000047' --start-pos=3346 --end-pos=3556 -B
    輸出:
    INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-10 00:04:56', 4, '小李'); #start 3346 end 3556
    INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-10 00:04:51', 3, '小孫'); #start 3346 end 3556
    INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-10 00:04:48', 2, '小錢'); #start 3346 end 3556
    INSERT INTO `test`.`tbl`(`addtime`, `id`, `name`) VALUES ('2016-12-10 00:04:33', 1, '小趙'); #start 3346 end 3556
  4. 確認回滾sql正確,執行回滾語句。登陸mysql確認,數據回滾成功。

    $ python binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttbl --start-file='mysql-bin.000047' --start-pos=3346 --end-pos=3556 -B | mysql -h127.0.0.1 -P3306 -uadmin -p'admin'
    
    mysql> select * from tbl;
    +----+--------+---------------------+
    | id | name   | addtime             |
    +----+--------+---------------------+
    |  1 | 小趙   | 2016-12-10 00:04:33 |
    |  2 | 小錢   | 2016-12-10 00:04:48 |
    |  3 | 小孫   | 2016-12-10 00:04:51 |
    |  4 | 小李   | 2016-12-10 00:04:56 |
    +----+--------+---------------------+

至此,不用再擔憂被炒魷魚了。

常見問題

  • 有人會問,我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回滾表結構,數據是回滾不了滴~ 還有一種作法叫slave延時備份,搞臺不加業務流量的slave,故意延遲一段時間,這實際上是在傳統辦法的基礎上去除了實例恢復這步。此法會額外消耗一臺機器,咱們不推薦這麼作。

若有mysql回滾相關的優秀工具優秀文章遺漏,煩請告知。

個人郵箱 danfengcao.info@gmail .com

參考資料

[1] 彭立勳, MySQL下實現閃回的設計思路

[2] Lixun Peng, Provide the flashback feature by binlog

[3] 丁奇, MySQL閃回方案討論及實現

[4] xiaobin lin, flashback from binlog for MySQL

[5] 王竹峯, 去哪兒inception

[6] danfengcao, binlog2sql: Parse MySQL binlog to SQL you want

相關文章
相關標籤/搜索