MySQL根據離線binlog快速「閃回」

2021-09-17 01:28:12 字數 2509 閱讀 4056

昨天突然有個客戶說誤操作,自己刪除了大量資料,cto直接將我拉到乙個討論組裡,說要幫他們恢復資料。他們自己挖的坑,打算讓開發那邊根據業務日誌去恢復,被告知只記錄的刪除主鍵這樣的資訊,物理刪除,無能為力。

上伺服器看了下記錄的日誌,發現好幾臺上面都有被誤刪的記錄輸出。阿里rds雖然可以轉殖乙個恢復到刪除時間點前的例項,但這散落的幾萬個id找起來費力,還有就是幾個表之間關聯的資料也要恢復,覺得麻煩。

正文開始

mysql(含阿里rds)快速閃回可以說是對資料庫誤操作的後悔藥,flashback功能可以將資料庫返回到誤操作之前。但是即使oracle資料庫也只支援短時間內的閃回。

網上現有開源的mysql閃回實現,原理都是解析binlog,生成反向sql: (必須為row模式)

對於 delete 操作,生成insert (delete_rows_event)

對於 update 操作,交換binlog裡面值的順序 (update_rows_event)

對於 insert 操作,反向生成delete (write_rows_event)

對於多個event,要逆向生成sql

開源實現:

上面兩種實現方式,都是通過 python-mysql-replication 包,模擬出原庫的乙個從庫,然後show binary logs來獲取binlog,發起同步binlog的請求,再解析event。但是阿里雲 rds 的binlog在同步給從庫之後,很快就被 purge 掉了。如果要恢復昨天部分資料,兩種方案都是拿不到binlog的。也就是閃回的時間有限。

還有一些比較簡單的實現,就是解析 binlog 物理檔案,實現回滾,如binlog-rollback.pl,試過,但是速度太慢。

為了不影響速度,又想使用比較成熟的閃回方案,我們可以這樣做:

借助乙個自建的 mysqld 例項,將已purge掉的binlog拷貝到該例項的目錄下

在自建例項裡,提前建立好需要恢復的表(結構),因為工具需要連線上來從information_schema.columns獲取元資料資訊

拷貝的時候,可以替換掉mysql例項自己的binlog檔名,保持連續

可能要修改mysql-bin.index,確保檔名還能被mysqld識別到

重啟mysql例項,show binary logs看一下是否在列表裡面

接下來就可以使用上面任何一種工具,模擬從庫,指定乙個binlog檔案,開始時間,結束時間,得到回滾sql

再根據業務邏輯,篩選出需要的sql

兩個例項間版本不要跨度太大

注意檔案許可權

如果原庫開啟了gtid,這個自建例項也要開啟gtid

示例:

python mysqlbinlog_back.py --host="localhost" --username="ecuser" --password="ecuser" --port=3306 \

--schema=dbname --tables="t_xx1,t_xx2,t_xx3" -s "mysql-bin.000019" -e "2017-03-02 13:00:00" -n "2017-03-02 14:09:00" -i -u

===log will also write to .//mysqlbinlog_flashback.log===

parameter=, 'add_schema_name': false, 'start_time': none, 'keep_current_data': false, 'start_to_timestamp': 1488430800,

'mysql_setting': ,

'table_name': 't_xx1,t_xx2,t_xx3', 'skip_delete': false, 'schema': 'dbname', 'stat': },

'table_name_array': ['t_xx1', 't_xx2', 't_xx3'],

'one_binlog_file': false, 'output_file_path': './log', 'start_position': 4, 'skip_update': true,

'dump_event': false, 'end_to_timestamp': 1488434940, 'skip_insert': true, 'schema_array': ['dbname']

}scan 10000 events ....from binlogfile=mysql-bin.000019,timestamp=2017-03-02t11:42:14

scan 20000 events ....from binlogfile=mysql-bin.000019,timestamp=2017-03-02t11:42:29

...

mysqlbinlog_back.py 使用經驗

參考

MySQL開啟binlog日誌

mysql開啟binlog日誌很簡單,只需要找到配置檔案,在配置檔案中的 mysqld 配置段新增下面一句話就可以了 log bin mysql bin 這樣就開啟了mysql的binlog日誌。使用下面的sql語句在mysql的客戶端可以檢視binlog日誌是否開啟 show master log...

mysql 匯出binlog日誌

首先你得開啟了mysql的bin log.找到你的mysqlbinlog。執行 find name mysqlbinlog 檢視mysql server上的二進位制日誌 mysql showbinarylogs 將binlog檔案匯出為sql檔案 usr local src mysql 5.7.10...

Mysql開啟binlog 實踐

mysql binlog是mysql資料庫的二進位制日誌,用於記錄使用者對資料庫操作的sql語句 除了資料查詢語句 資訊。binlog的格式也有三種 statement row mixed 我使用的是用docker安裝的mysql,所以需要提前掛載好配置檔案。開啟binlog方法 1 找到 my,c...