平常開發,運維中,常常會出現誤刪數據的狀況。誤刪數據的類型大體可分爲如下幾類:html
不一樣的狀況,都會有其優先的解決方案:mysql
本篇主要討論的內容是誤刪表或者庫,會先介紹有關 BINLOG 的操做命令,而後會對誤刪表的這種狀況進行實際的模擬。sql
BINLOG 的查詢方式通常分爲兩種,一種是進入 MySQL 控制檯進行查詢,另外一種是經過 MySQL 提供的工具 mysqlbinlog 進行查詢,二者的不一樣會在下面介紹。shell
在 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
limit
,會引起對資源的過分消耗。由於 MySQL 客戶端須要將 binlog 的所有內容處理,返回並顯示出來。爲了防止這種狀況,mysqlbinlog 工具是一個很好的選擇。在介紹 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 的用途有哪些?:工具
查詢 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 中正在寫入的 BINLOG 的名稱,大小等基本信息時,能夠經過 Cli 相關的命令來查詢。
但想查詢,定位,恢復 BINLOG 中具體的數據時,要經過 mysqlbinlog 工具,由於相較於 Cli 來講,mysqlbinlog 提供了 --start-datetime
,--stop-position
等這樣更爲豐富的參數供咱們選擇。這時 Cli 中 SHOW BINLOG EVENTS
的簡要語法就變得相形見絀了。
恢復的大體流程以下:
準備數據庫,表及數據:
# 建立臨時數據庫 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 文件 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' 的位置:
# 根據位置導出 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-position
和 end-position
的一些小細節,來保證找到合適的位置。