1. 程式人生 > >Mysql數據閃回的奇技淫巧(binlog2sql)

Mysql數據閃回的奇技淫巧(binlog2sql)

mysql binlog2sql

一、概述

binlog2sql是一個開源項目,應用於大眾點評線上環境。類似於ORACLE中的閃回功能,binlog2sql可以基於時間點或者位置偏移量進行數據恢復。MySQL binlog解析出你要的SQL。根據不同選項,你可以得到原始SQL、回滾SQL、去除主鍵的INSERT SQL等。也就是對於insert操作會生成對應的delete語句,反之delete操作會生出對應的insert語句,update操作會生成相反的語句。

關於binlog2sql閃回詳細介紹可參閃回原理與實戰。我也是偶然間看到一個大神關於這個神器的介紹,猛然心動,決心要動手演練一把。

我的測試環境介紹

l Python 2.

6

l MySQL 5.1.73

二、binlog2sql安裝

binlog2sql工具可以自己下載 https://github.com/danfengcao/binlog2sql

下面這些包都要裝全,否則執行腳本會報錯

python-pip

PyMySQL

python-mysql-replication

argparse

Linux機器下載並安裝binlog2sql

[root@DB binlog2sql-master]# wget  https://codeload.github.com/danfengcao/binlog2sql/zip/master
[root@DB install_page]# unzip binlog2sql-master.zip 
Archive:  binlog2sql-master.zip
bb09b8f9079ca4d3cacd0186f35ddf4b3e1cfa7e
   creating: binlog2sql-master/
  inflating: binlog2sql-master/.gitignore  
  inflating: binlog2sql-master/LICENSE  
  inflating: binlog2sql-master/README.md  
   creating: binlog2sql-master/binlog2sql/
  inflating: binlog2sql-master/binlog2sql/__init__.py  
  inflating: binlog2sql-master/binlog2sql/binlog2sql.py  
  inflating: binlog2sql-master/binlog2sql/binlog2sql_util.py  
   creating: binlog2sql-master/example/
  inflating: binlog2sql-master/example/mysql-flashback-priciple-and-practice.md  
  inflating: binlog2sql-master/requirements.txt  
   creating: binlog2sql-master/tests/
  inflating: binlog2sql-master/tests/test_binlog2sql_util.py  
[root@DB install_page]# ls
binlog2sql-master  binlog2sql-master.zip  
[root@DB binlog2sql-master]# cd binlog2sql-master #下面腳本執行的時候也要在這麽路徑下
[root@DB binlog2sql-master]# pip install -r requirements.txt 
Downloading/unpacking PyMySQL==0.7.11 (from -r requirements.txt (line 1))
  Downloading PyMySQL-0.7.11.tar.gz (71kB): 71kB downloaded
  Running setup.py egg_info for package PyMySQL
Downloading/unpacking wheel==0.29.0 (from -r requirements.txt (line 2))
  Downloading wheel-0.29.0.tar.gz (54kB): 54kB downloaded
  Running setup.py egg_info for package wheel
    no previously-included directories found matching 'wheel/test/*/dist'
    no previously-included directories found matching 'wheel/test/*/build'
Downloading/unpacking mysql-replication==0.13 (from -r requirements.txt (line 3))
  Downloading mysql-replication-0.13.tar.gz
  Running setup.py egg_info for package mysql-replication
Installing collected packages: PyMySQL, wheel, mysql-replication
  Running setup.py install for PyMySQL
  Running setup.py install for wheel
    no previously-included directories found matching 'wheel/test/*/dist'
    no previously-included directories found matching 'wheel/test/*/build'
    Installing wheel script to /usr/bin
  Running setup.py install for mysql-replication
Successfully installed PyMySQL wheel mysql-replication
Cleaning up...

三、Mysql環境要求

1MySQL server必須設置以下參數:

[mysqld]
server-id=160
log-bin=mysql-binlog
max_binlog_size=1G
binlog_format=row

2創建一個閃回用戶

root@localhost test1 19:48:06> create user test@'%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
root@localhost test1 19:49:06>grant select,replication slave,replication client on *.* to test@'%';
Query OK, 0 rows affected (0.00 sec)
 
root@localhost test1 19:49:50>flush privileges;
Query OK, 0 rows affected (0.00 sec)

註:user需要的最小權限集合:

select, super/replication client, replication slave

權限說明

select:需要讀取server端information_schema.COLUMNS表,獲取表結構的元信息,拼接成可視化的sql語句
super/replication client:兩個權限都可以,需要執行'SHOW MASTER STATUS', 獲取server端的binlog列表
replication slave:通過BINLOG_DUMP協議獲取binlog內容的權限


3、 模擬一次生產事故,誤刪數據

test1tb1表原有數據

root@localhost test1 20:08:52>select * from tb1;
+-------+------+
| name  | age  |
+-------+------+
| kobe  |   21 |
| james |   22 |
| jack  |   23 |
| mike  |   24 |
| bob   |   25 |
+-------+------+
5 rows in set (0.01 sec)
 
root@localhost test1 20:08:59>delete from tb1 where age <23;
Query OK, 2 rows affected (0.00 sec)
 
root@localhost test1 20:09:03>select * from tb1;
+-------+------+
| name  | age  |
+-------+------+
| jack  |   23 |
| mike  |   24 |
| bob   |   25 |
+-------+------+
3 rows in set (0.01 sec)

四、恢復數據步驟

1登錄mysql,查看目前的binlog文件

root@localhost test1 20:09:59>show master status;
+---------------------+----------+--------------+------------------+
| File                | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------------+----------+--------------+------------------+
| mysql-binlog.000002 |      341 |              |                  |
+---------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

最新的binlog文件是mysql-binlog.000002,我們再定位誤操作SQLbinlog位置。誤操作人只能知道大致的誤操作時間,我們根據大致時間過濾數據。

2接下來就該這個神器登場了。

先來介紹一下binlog2sql參數

--stop-never 持續同步binlog。可選。不加則同步至執行命令時最新的binlog位置。
-K, --no-primary-key 對INSERT語句去除主鍵。可選。
-B, --flashback 生成回滾語句,可解析大文件,不受內存限制,每打印一千行加一句SELECT SLEEP(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。可選。默認為空。


3、 根據預估時間,執行下面命令找出對應的position

[root@DB binlog2sql]# python binlog2sql.py -h 192.168.221.160 -utest -p123456 -dtest1 -ttb1 --start-file='mysql-binlog.000002' --start-datetime='2017-12-04 20:00:00' --stop-datetime='2017-12-04 20:10:00' 
DELETE FROM `test1`.`tb1` WHERE `age`=21 AND `name`='kobe' LIMIT 1; #start 4 end 271 time 2017-12-04 20:08:59
DELETE FROM `test1`.`tb1` WHERE `age`=22 AND `name`='james' LIMIT 1; #start 4 end 271 time 2017-12-04 20:08:59

我們得到了誤操作sql的準確位置在4-271之間,再根據位置進一步過濾,使用flashback模式生成回滾sql,檢查回滾sql是否正確(註:真實環境下,此步經常會進一步篩選出需要的sql。結合grep、編輯器等)

4、 使用flashback模式生成回滾sql

[root@DB binlog2sql]# python binlog2sql.py -h 192.168.221.160 -utest -p123456 -dtest1 -ttb1 --start-file='mysql-binlog.000002' --start-position=4 --stop-position=271 -B > tb1_rollback.sql

查看閃回導出的文件

[root@DB binlog2sql]# cat tb1_rollback.sql 
INSERT INTO `test1`.`tb1`(`age`, `name`) VALUES (22, 'james'); #start 4 end 271 time 2017-12-04 20:08:59
INSERT INTO `test1`.`tb1`(`age`, `name`) VALUES (21, 'kobe'); #start 4 end 271 time 2017-12-04 20:08:59

5確認回滾sql正確,執行回滾語句。登錄mysql確認,數據回滾成功。

[root@DB binlog2sql]# mysql -uroot test1 -p123456 <tb1_rollback.sql 
Enter password:


6、登錄數據庫檢驗數據完整性

root@localhost test1 20:18:04>select * from tb1;
+-------+------+
| name  | age  |
+-------+------+
| kobe  |   21 |
| james |   22 |
| jack  |   23 |
| mike  |   24 |
| bob   |   25 |
+-------+------+
5 rows in set (0.00 sec)

可以看到,之前刪除的兩條數據又回來了

五、結語

binlog2sql是屬於Python開發,安裝與使用都很簡單,易於上手,可操作性強,解析為標準SQL,方便理解、調試。但仍存在一些缺點,比如只能在mysql開啟的狀態下運行,不能離線操作,數據量較大時會暴露出解析速度慢的問題。總體來說,仍不失成為一個很NICE的工具。


Mysql數據閃回的奇技淫巧(binlog2sql)