使用binlog2sql恢復數據

誤刪除數據的話,oracle裏面咱們可使用閃回功能找回誤操做的數據。python

在MySQL裏面,若是咱們有延遲從庫的話,也能夠找回以前的數據,可是有時候不太好使(由於追數據到誤操做前的準確的時間點有時候也不太好把握)。mysql

對於誤操做數據的閃回,咱們通常推薦 binlog2sql 或者MyFlash(美團點評開源的)git


本篇文章, 咱們介紹下 binlog2sql的用法:github




binlog2sql 【首級推薦使用】sql

官網:https://github.com/danfengcao/binlog2sql數據庫

注意: binlog必須是row格式,而且是FULL類型的記錄。centos

安裝: bash

yum update nss curl libcurl -y   # centos6須要升級下這個包,否則無法去github拉代碼
cd /root/
git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql
pip install -r requirements.txt


受權:oracle

> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'flashback'@'192.168.11.20' identified by 'admin';



> USE testdb;curl

[testdb] > SELECT * FROM t_stud WHERE name LIKE 'Y%';

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|     5 | Yu Wutong     |  26 | M      |       3 |         1 |

|    10 | Lee Lingshan  |  19 | F      |       3 |      NULL |

|    11 | John Chengzhi |  23 | M      |       6 |      NULL |

+-------+---------------+-----+--------+---------+-----------+


[testdb] > UPDATE t_stud SET age=100 WHERE name LIKE 'Y%';    -- 看到有3行受到影響

Query OK, 3 rows affected (0.01 sec)

Rows matched: 3  Changed: 3  Warnings: 0


[testdb] > SELECT * FROM t_stud WHERE name LIKE 'Y%';

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|     5 | Yu Wutong     | 100 | M      |       3 |         1 |

|    10 | Lee Lingshan  | 100 | F      |       3 |      NULL |

|    11 | John Chengzhi | 100 | M      |       6 |      NULL |

+-------+---------------+-----+--------+---------+-----------+



解析出標準SQL:

cd /root/ 
先用mysqlbinlog找到誤操做的那個地方binlog文件及位移點,而後使用下面命令解析:
python /root/binlog2sql/binlog2sql/binlog2sql.py -h192.168.11.20 -P3306 -uflashback -p'admin' -d testdb -t t_stud --start-file='mysql-bin.000040' --start-position=10030 --stop-position=10334


1 解析出回滾SQL:

cd /root/ 
python /root/binlog2sql/binlog2sql/binlog2sql.py --flashback -h192.168.11.20 -P3306 -uflashback -p'admin' -d testdb -t t_stud --start-file='mysql-bin.000040' --start-position=10030 --stop-position=10334

解析出的結果相似這樣:

UPDATE `testdb`.`t_stud` SET `StuID`=11, `Name`='John Chengzhi', `Age`=23, `Gender`='M', `ClassID`=6, `TeacherID`=NULL WHERE `StuID`=11 AND `Name`='John Chengzhi' AND `Age`=100 AND `Gender`='M' AND `ClassID`=6 AND `TeacherID` IS NULL LIMIT 1; #start 10030 end 10334 time 2018-07-15 14:17:58
UPDATE `testdb`.`t_stud` SET `StuID`=10, `Name`='Lee Lingshan', `Age`=19, `Gender`='F', `ClassID`=3, `TeacherID`=NULL WHERE `StuID`=10 AND `Name`='Lee Lingshan' AND `Age`=100 AND `Gender`='F' AND `ClassID`=3 AND `TeacherID` IS NULL LIMIT 1; #start 10030 end 10334 time 2018-07-15 14:17:58
UPDATE `testdb`.`t_stud` SET `StuID`=5, `Name`='Yu Wutong', `Age`=26, `Gender`='M', `ClassID`=3, `TeacherID`=1 WHERE `StuID`=5 AND `Name`='Yu Wutong' AND `Age`=100 AND `Gender`='M' AND `ClassID`=3 AND `TeacherID`=1 LIMIT 1; #start 10030 end 10334 time 2018-07-15 14:17:58


2 修復下數據,去掉結尾的#及後面的內容:

sed -i.bak  's/#.*//g' /root/rollback.sql



3 將數據恢復到數據庫中:

use testdb ;
UPDATE `testdb`.`t_stud` SET `StuID`=11, `Name`='John Chengzhi', `Age`=23, `Gender`='M', `ClassID`=6, `TeacherID`=NULL WHERE `StuID`=11 AND `Name`='John Chengzhi' AND `Age`=100 AND `Gender`='M' AND `ClassID`=6 AND `TeacherID` IS NULL LIMIT 1;
UPDATE `testdb`.`t_stud` SET `StuID`=10, `Name`='Lee Lingshan', `Age`=19, `Gender`='F', `ClassID`=3, `TeacherID`=NULL WHERE `StuID`=10 AND `Name`='Lee Lingshan' AND `Age`=100 AND `Gender`='F' AND `ClassID`=3 AND `TeacherID` IS NULL LIMIT 1; 
UPDATE `testdb`.`t_stud` SET `StuID`=5, `Name`='Yu Wutong', `Age`=26, `Gender`='M', `ClassID`=3, `TeacherID`=1 WHERE `StuID`=5 AND `Name`='Yu Wutong' AND `Age`=100 AND `Gender`='M' AND `ClassID`=3 AND `TeacherID`=1 LIMIT 1;


執行完後,再次看下數據,能夠看到已經恢復好了。

[testdb] > select * from t_stud where name like 'Y%';                                                                                                                                                   

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|     5 | Yu Wutong     |  26 | M      |       3 |         1 |

|    10 | Lee Lingshan  |  19 | F      |       3 |      NULL |

|    11 | John Chengzhi |  23 | M      |       6 |      NULL |

+-------+---------------+-----+--------+---------+-----------+


補充:

解析模式:

--stop-never 持續同步binlog。可選。不加則同步至執行命令時最新的binlog位置。

-K, --no-primary-key 對INSERT語句去除主鍵。可選。

-B, --flashback 生成回滾語句,可解析大文件,不受內存限制,每打印一千行加一句SLEEP SELECT(1)。可選。與stop-never或no-primary-key不能同時添加。

解析範圍控制:

--start-file 起始解析文件。必須。

--start-position/--start-pos start-file的起始解析位置。可選。默認爲start-file的起始位置。

--stop-file/--end-file 末尾解析文件。可選。默認爲start-file同一個文件。若解析模式爲stop-never,此選項失效。

--stop-position/--end-pos stop-file的末尾解析位置。可選。默認爲stop-file的最末位置;若解析模式爲stop-never,此選項失效。

--start-datetime 從哪一個時間點的binlog開始解析,格式必須爲datetime,如'2016-11-11 11:11:11'。可選。默認不過濾。

--stop-datetime 到哪一個時間點的binlog中止解析,格式必須爲datetime,如'2016-11-11 11:11:11'。可選。默認不過濾。

對象過濾:

-d, --databases 只輸出目標db的sql。可選。默認爲空。

-t, --tables 只輸出目標tables的sql。可選。默認爲空。


注意: 

提取出來的sql 其實是倒序的。

例如誤操做的sql是以下2步:  2018101916 ---> 11 ---> 12

step0: 原始t1表的 work_id='2018101916' 

step1: update test.t1 set work_id='11' where id=32 limit 1 ;  # 簡單實驗,update不更新其它列的數據

step2: update test.t1 set work_id='22' where id=32 limit 1 ;  # 簡單實驗,update不更新其它列的數據

閃回出來的sql是這樣的:  12 ---> 11 ---> 2018101916

UPDATE `test`.`t1` SET `id`=32, `work_id`='11', `username`='admin' LIMIT 1;

UPDATE `test`.`t1` SET `id`=32, `work_id`='2018101916', `username`='admin' LIMIT 1;

相關文章
相關標籤/搜索