MySQL 5.7 - 經過 BINLOG 恢復數據

平常開發,運維中,常常會出現誤刪數據的狀況。誤刪數據的類型大體可分爲如下幾類:html

  • 使用 delete 誤刪行
  • 使用 drop table 或 truncate table 誤刪表
  • 使用 drop database 語句誤刪數據庫
  • 使用 rm 命令誤刪整個 MySQL 實例。

不一樣的狀況,都會有其優先的解決方案:mysql

  • 針對誤刪行,能夠經過 Flashback 工具將數據恢復
  • 針對誤刪表或庫,通常採用經過 BINLOG 將數據恢復。
  • 而對於誤刪 MySQL 實例,則須要咱們搭建 HA 的 MySQL 集羣,並保證咱們的數據跨機房,跨城市保存。

本篇主要討論的內容是誤刪表或者庫,會先介紹有關 BINLOG 的操做命令,而後會對誤刪表的這種狀況進行實際的模擬。sql

BINLOG 常見操做命令

BINLOG 的查詢方式通常分爲兩種,一種是進入 MySQL 控制檯進行查詢,另外一種是經過 MySQL 提供的工具 mysqlbinlog 進行查詢,二者的不一樣會在下面介紹。shell

經過 MySQL Cli 查詢 BINLOG 信息

在 cli 中,常見的命令以下:數據庫

# 查詢 BINLOG 格式
show VARIABLES like 'binlog_format';

# 查詢 BINLOG 位置
show VARIABLES like 'datadir';

# 查詢當前數據庫中 BINLOG 名稱及大小
show binary logs;

# 查看 master 正在寫入的 BINLOG 信息
show master status\G;

# 經過 offset 查看 BINLOG 信息
show BINLOG events in 'mysql-bin.000034' limit 9000,  10;

# 經過 position 查看 binlog 信息
show BINLOG events in 'mysql-bin.000034' from 1742635 limit 10;

使用 show BINLOG events 的問題:less

  • 使用該命令時,若是當前 binlog 文件很大,並且沒有指定 limit,會引起對資源的過分消耗。由於 MySQL 客戶端須要將 binlog 的所有內容處理,返回並顯示出來。爲了防止這種狀況,mysqlbinlog 工具是一個很好的選擇。

經過 mysqlbinlog 查詢 BINLOG 信息:

在介紹 mysqlbinlog 工具使用前,先來看下 BINLOG 文件的內容:運維

# 查詢 BINLOG 的信息
mysqlbinlog  --no-defaults mysql-bin.000034 | less
# at 141
#100309  9:28:36 server id 123  end_log_pos 245
  Query thread_id=3350  exec_time=11  error_code=0
  • at 表示 offset 或者說事件開始的起始位置
  • 100309 9:28:36 server id 123 表示 server 123 開始執行事件的日期
  • end_log_pos 245 表示事件的結束位置 + 1,或者說是下一個事件的起始位置。
  • exec_time 表示在 master 上花費的時間,在 salve 上,記錄的時間是從 Master 記錄開始,一直到 Slave 結束完成所花費的時間。
  • rror_code=0 表示沒有錯誤發生。

在大體瞭解 binlog 的內容後,mysqlbinlog 的用途有哪些?:工具

  • mysqlbinlog 能夠做爲代替 cli 讀取 binlog 的工具。
  • mysqlbinlog 能夠將執行過的 SQL 語句輸出,用於數據的恢復或備份。

查詢 BINLOG 日誌:編碼

# 查詢規定時候後發生的 BINLOG 日誌
mysqlbinlog --no-defaults --base64-output=decode-rows -v  --start-datetime  "2019-11-22 14:00:00" --database sync_test  mysql-bin.000034 | less

導出 BINLOG 日誌,用於分析和排查 sql 語句:日誌

mysqlbinlog --no-defaults --base64-output=decode-rows -v  --start-datetime  "2019-11-22 14:00:00" --database sync_test  mysql-bin.000034 > /home/mysql_backup/binlog_raw.sql

導入 BINLOG 日誌

# 經過 BINLOG 進行恢復。
mysqlbinlog --start-position=1038 --stop-position=1164 --database=db_name  mysql-bin.000034 | mysql  -u cisco -p db_name

# 經過 BINLOG 導出的 sql 進行恢復。
mysql -u cisco -p db_name < binlog_raw.sql.sql

mysqlbinlog 的經常使用參數:

  • --database 僅僅列出配置的數據庫信息
  • --no-defaults 讀取沒有選項的文件, 指定的緣由是因爲 mysqlbinlog 沒法識別 BINLOG 中的 default-character-set=utf8 指令
  • --offset 跳過 log 中 N 個條目
  • --verbose 將日誌信息重建爲原始的 SQL 陳述。
    • -v 僅僅解釋行信息
    • -vv 不但解釋行信息,還將 SQL 列類型的註釋信息也解析出來
  • --start-datetime 顯示從指定的時間或以後的時間的事件。
    • 接收 DATETIME 或者 TIMESTRAMP 格式。
  • --base64-output=decode-rows 將 BINLOG 語句中事件以 base-64 的編碼顯示,對一些二進制的內容進行屏蔽。
    • AUTO 默認參數,自動顯示 BINLOG 中的必要的語句
    • NEVER 不會顯示任何的 BINLOG 語句,若是遇到必須顯示的 BINLOG 語言,則會報錯退出。
    • DECODE-ROWS 顯示經過 -v 顯示出來的 SQL 信息,過濾到一些 BINLOG 二進制數據。

MySQL Cli 和 mysqlbinlog 工具之間的比較

若是想知道當前 MySQL 中正在寫入的 BINLOG 的名稱,大小等基本信息時,能夠經過 Cli 相關的命令來查詢。

但想查詢,定位,恢復 BINLOG 中具體的數據時,要經過 mysqlbinlog 工具,由於相較於 Cli 來講,mysqlbinlog 提供了 --start-datetime--stop-position 等這樣更爲豐富的參數供咱們選擇。這時 Cli 中 SHOW BINLOG EVENTS 的簡要語法就變得相形見絀了。

使用 BINLOG 恢復數據

恢復的大體流程以下:

  1. 會建立數據庫和表,並插入數據。
  2. 誤刪一條數據。
  3. 繼續多條數據。
  4. 誤刪表。
  5. 最後將原來中的以及全部的數據進行恢復。

準備數據

準備數據庫,表及數據:

# 建立臨時數據庫
CREATE DATABASE IF NOT EXISTS test_binlog default charset utf8 COLLATE utf8_general_ci; 


# 建立臨時表
CREATE TABLE `sync_test` (`id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


# 添加數據
insert into sync_test (id, name) values (null, 'xiaoa');
insert into sync_test (id, name) values (null, 'xiaob');
insert into sync_test (id, name) values (null, 'xiaoc');

# 查看添加的數據
select * from sync_test;

刪除表或者數據

誤刪操做:

# 刪除 name=xiaob 的數據
delete from sync_test where id=3

# 插入幾條數據
insert into sync_test (id, name) values (null, 'xiaod');
insert into sync_test (id, name) values (null, 'xiaoe');
insert into sync_test (id, name) values (null, 'xiaof');

# 刪除表
DROP TABLE sync_test;

數據的恢復

在執行數據恢復前,若是操做的是生產環境,會有以下的建議:

  • 使用 flush logs 命令,替換當前主庫中正在使用的 binlog 文件,好處以下:
    • 可將誤刪操做,定位在一個 BINLOG 文件中,便於以後的數據分析和恢復。
    • 避免操做正在被使用的 BINLOG 文件,防止發生意外狀況。
  • 數據的恢復不要在生產庫中執行,先在臨時庫恢復,確認無誤後,再倒回生產庫。防止對數據的二次傷害。

一般來講,恢復主要有兩個步驟:

  1. 在臨時庫中,恢復按期執行的全量備份數據。
  2. 而後基於全量備份的數據點,經過 BINLOG 來恢復誤操做和正常的數據。

使用 BINLOG 作數據恢復前:

# 查看正在使用的 Binlog 文件
show master status\G;
# 顯示結果是: mysql-bin.000034

# 執行 flush logs 操做,生成新的 BINLOG
flush logs;

# 查看正在使用的 Binlog 文件
show master status\G;
# 結果是:mysql-bin.000035

肯定恢復數據的步驟:

這裏主要是有兩條誤刪的操做,數據行的誤刪和表的誤刪。有兩種方式進行恢復。

  • 方式一:首先恢復到刪除表操做以前的位置,而後再單獨恢復誤刪的數據行。
  • 方式二:首先恢復到誤刪數據行的以前的位置,而後跳過誤刪事件再恢復數據表操做以前的位置。

這裏採用方式一的方案進行演示,因爲是演示,就不額外找一個臨時庫進行全量恢復了,直接進行操做。

查詢建立表的事件位置和刪除表的事件位置

#  根據時間肯定位置信息
mysqlbinlog --no-defaults --base64-output=decode-rows -v  --start-datetime  "2019-11-22 14:00:00" --database test_binlog  mysql-bin.000034 | less

建立表的開始位置:

建立表的開始位置

刪除表的結束位置:

刪除表的結束位置

插入 name='xiaob' 的位置:

插入 name='xiaob' 的位置

# 根據位置導出 SQL 文件
mysqlbinlog --no-defaults --base64-output=decode-rows -v --start-position "2508132" --stop-position "2511004" --database test_binlog  mysql-bin.000034 > /home/mysql_backup/test_binlog_step1.sql
 
 
mysqlbinlog --no-defaults --base64-output=decode-rows -v --start-position "2508813" --stop-position "2509187" --database test_binlog  mysql-bin.000034 > /home/mysql_backup/test_binlog_step2.sql
 

# 使用 mysql 進行恢復
mysql -u cisco -p < /home/mysql_backup/test_binlog_step1.sql
mysql -u cisco -p < /home/mysql_backup/test_binlog_step2.sql

MySQL 5.7 中不管是否打開 GTID 的配置,在每次事務開啓時,都首先會出 GTID 的一個事務,用於並行複製。因此在肯定導出開始事務位置時,要算上這個事件。

在使用 --stop-position 導出時,會導出在指定位置的前一個事件,因此這裏要推後一個事務。

對於 DML 的語句,主要結束位置要算上 COMMIT 的位置。

總結

在文章開始時,咱們熟悉了操做 BINLOG 的兩種方式 CLI 和 mysqlbinlog 工具,接着介紹了其間的區別和使用場景,對於一些大型的 BINLOG 文件,使用 mysqlbinlog 會更加的方便和效率。並對 mysqlbinlog 的一些常見參數進行了介紹。

接着經過使用 mysqlbinlog 實際模擬了數據恢復的過程,並在恢復數據時,提出了一些須要注意的事項,好比 flush logs 等。

最後在恢復數據時,要注意 start-positionend-position 的一些小細節,來保證找到合適的位置。

參考

point-in-time-recovery

recovery-from-backups

backup-policy.

相關文章
相關標籤/搜索