MySQL 經過 binlog 恢復數據

目的

經過了解 binlog 日誌的相關配置,簡單掌握經過 binlog 對數據庫進行數據恢復操做;php

mysql 日誌文件

任何成熟軟件都會有一套成熟的日誌系統,當軟件出現問題時,這些日誌就是查詢問題來源的寶庫。一樣,mysql 也不例外,也會有一系列日誌記錄 mysql 的運行狀態。mysql

mysql 主要有如下幾種日誌:sql

  • 錯誤日誌:記錄 mysql 運行過程當中的錯誤信息
  • 通常查詢日誌:記錄mysql正在運行的語句,包括查詢、修改、更新等的每條 sql
  • 慢查詢日誌:記錄查詢比較耗時的 SQL 語句
  • binlog 日誌:記錄數據修改記錄,包括建立表、數據更新等

這些日誌均須要在 my.cnf 文件進行配置,若是不知道 mysql 的配置文件路徑,可使用 mysql 命令進行查找,數據庫

mysql --verbose --help|grep -A 1 'Default options’ #該命令會羅列出my.cnf 順序查找的路徑。

binlog 日誌

binlog 就是 binary log,二進制日誌文件,記錄全部數據庫更新語句,包括表更新和記錄更新,即數據操縱語言(DML),binlog 主要用於數據恢復和配置主從複製等;工具

  • 數據恢復:當數據庫誤刪或者發生不可描述的事情時,能夠經過 binlog 恢復到某個時間點的數據。
  • 主從複製:當有數據庫更新以後,主庫經過 binlog 記錄並通知從庫進行更新,從而保證主從數據庫數據一致;

mysql 按照功能分爲服務層模塊和存儲引擎層模塊,服務層負責客戶端鏈接、SQL 語句處理優化等操做,存儲引擎層負責數據的存儲和查詢;binlog 屬於服務層模塊的日誌,即引擎無關性,全部數據引擎的數據更改都會記錄binlog日誌。當數據庫發生崩潰時,若是使用InnoDB 引擎,binlog 日誌還能夠檢驗 InnoDB 的 redo 日誌的 commit 狀況。優化

binlog 日誌開啓

日誌開啓方式:

一、添加配置日誌

log_bin=ON
log_bin_basename=/path/bin-log
log_bin_index=/path/bin-log.index

二、僅僅設置log-bin參數code

log-bin=/path/bin-log

當開啓 binlog 日誌以後,mysql 會建立一個 log_bin_index 指定的 .index 文件和多個二進制日誌文件,index 中按順序記錄了mysql使用的全部 binlog 文件。binlog 日誌則會以指定的名稱(或默認值) 加自增的數字做爲後綴,ex:bin-log.000001,當發生下述三種狀況時,binlog 日誌便會進行重建:orm

文件大小達到 max_binlog_size 參數的值
執行 flush logs 命令
重啓 mysql 服務

binlog 日誌格式

經過參數 binlog_format 參數的值,能夠設置 binlog 的格式,可選值有 statement、row、mixed文檔

* statement 格式:記錄數據庫執行的原始 SQL 語句
  * row 格式:記錄具體的行的修改,這個爲目前默認值
  * mixed 格式:由於上邊兩種格式各有優缺點,因此就出現了 mixed 格式

binlog 日誌查看工具:mysqlbinlog

由於 binlog 是二進制文件,不能像其餘文件同樣,直接打開查看。但 mysql 提供了binlog 查看工具 mysqlbinlog,能夠解析二進制文件。固然不一樣格式的日誌解析結果是不同的;

1. statement 格式日誌,執行 mysqlbinlog  /path/bin-log.000001,能夠直接看到原始執行的 SQL 語句
2. row格式日誌,則可讀性沒有那麼好,但仍可經過參數使文檔更加可讀 mysqlbinlog -v  /path/bin-log.000001

mysqlbinlog兩對很是重要的參數

1. --start-datetime  --stop-datetime 解析某一個時間段內的binlog;
  2. --start-position  --stop-position   解析在兩個position之間的binlog;

使用 binlog 恢復數據:

使用 binlog 恢復數據,本質上就是經過 binlog 找到全部 DML 操做,去掉錯誤的 SQL 語句,而後重走一遍長征路,就能夠將數據恢復;

線下實操:

  1. 建立數據表並插入初始值
CREATE TABLE `users` (
              `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
              `name` varchar(255) DEFAULT NULL,
              `age` int(8) DEFAULT NULL,
              PRIMARY KEY (`id`)
     ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
     INSERT INTO `users` (`id`, `name`, `age`)
        VALUES
            (null, '姓名一', 5);
  1. 找到上一次全量備份的數據庫和binlog的position(ps:固然也能夠經過時間進行恢復)。此處以目前狀態做爲備份的初始值,
mysqldump -uroot -p T > /path/xxx.sql;   # 備份數據庫
    show master status;   # 查看當前的position位置,此時值爲154
  1. 插入多條記錄
INSERT INTO `users` (`id`, `name`, `age`)
  VALUES
     (null, '姓名二', 13),
     (null, '姓名三', 14),
     (null, '姓名四', 15),
     (null, '姓名五', 16),
     (null, '姓名六', 17);
  1. 進行誤操做,而且在誤操做以後又插入幾條數據
update users set age = 5;
 INSERT INTO `users` (`id`, `name`, `age`)
 VALUES
    (null, '姓名七', 16),
    (null, '姓名八', 18);
  1. 發現誤操做以後,進行數據恢復,首先中止 mysql 對外的服務,利用備份數據恢復到上次數據;
  2. 經過 mysqlbinlog 命令對二進制文件進行分析,分析發現
誤操做發生在position爲706位置,且上次正常操做的結束位置在513
    在1152到結尾位置有正常執行的SQL執行
  1. 經過 mysqlbinlog 命令從 binlog 日誌中導出可執行的 SQL 文件,並將數據導入到mysql
mysqlbinlog --start-position=154  --stop-position=513  bin-log.000001 > /path/bak.sql;
 mysql -uroot -p < /path/bak.sql;
  1. 跳過錯誤的更新語句,再經過步驟7的邏輯把後續正常語句從新跑一遍,完成數據恢復工做

小結

不管什麼時間,數據庫發生崩潰都會使人愁眉緊鎖,心煩意亂。binlog能夠說是在各類狀況下,數據庫崩潰、數據丟失以後的一粒後悔藥,本文經過線下環境,簡單的對數據庫進行了一次數據恢復實驗,若有不對,還請指教

參考文章

http://www.ywnds.com/?p=12839
https://zhuanlan.zhihu.com/p/...

相關文章
相關標籤/搜索