《MySQL實戰45講》學習筆記2——MySQL的日誌系統

1、日誌類型sql

  • 邏輯日誌:存儲了邏輯SQL修改語句
  • 物理日誌:存儲了數據被修改的值
2、binlog
1.定義
binlog 是 MySQL 的 邏輯日誌,也叫二進制日誌、歸檔日誌,由 MySQL Server 來記錄。
用於記錄用戶對數據庫操做的SQL語句(除了查詢語句)信息,以二進制的形式保存在磁盤中。
 
2.記錄方式
binlog 經過 追加的方式寫入的,可經過配置參數 max_binlog_size 設置每一個 binlog 文件的大小,當文件大小大於給定值後,日誌會發生滾動,以後的日誌記錄到新的文件上。
 
3.格式 
binlog 日誌有三種格式,分別爲 STATMENT、ROW 和 MIXED。
 
 
STATMENT
ROW
說明
基於SQL語句的複製(statement-based replication, SBR),每一條會修改數據的sql語句會記錄到binlog中。
是bin log的默認格式。
基於行的複製(row-based replication, RBR):不記錄每一條SQL語句的上下文信息,僅保存哪條記錄被修改。
優勢
不須要記錄每一條SQL語句與每行的數據變化,減小了bin log的日誌量,節約了磁盤IO,提升性能。
會很是清楚的記錄下每一行數據修改的細節,不會出現某些特定狀況下的存儲過程、或function、或trigger的調用和觸發沒法被正確複製的問題。
缺點
在某些狀況下會致使master-slave中的數據不一致,如sleep()函數, last_insert_id(),以及user-defined functions(udf)等會出現問題。
會產生大量的日誌,尤爲是alter table的時候會讓日誌暴漲。
MIXED模式是基於 STATMENT 和 ROW 兩種模式的混合複製(mixed-based replication, MBR),通常的複製使用STATEMENT模式保存 binlog,對於 STATEMENT 模式沒法複製的操做使用ROW模式保存 binlog,MySQL 會根據執行的 SQL 語句選擇日誌保存方式。
 
3、redo log
1.定義:
redo log 是 MySQL 的 物理日誌,也叫重作日誌,記錄存儲引擎 InnoDB 的事務日誌。
 
MySQL 每執行一條 SQL 更新語句,不是每次數據更改都馬上寫到磁盤,而是先將記錄寫到 redo log 裏面,並更新內存(這時內存與磁盤的數據不一致,將這種有差別的數據稱爲 髒頁),一段時間後,再一次性將多個操做記錄寫到到磁盤上,這樣能夠減小磁盤 io 成本,提升操做速度。 先寫日誌,再寫磁盤,這就是 MySQL 裏常常說到的 WAL 技術,即 Write-Ahead Logging,又叫預寫日誌。MySQL 經過 WAL 技術保證事務的持久性。
 
2.記錄方式
InnoDB 的 redo log 大小是固定的,採用 循環寫的方式記錄,當寫到結尾時,會回到開頭循環寫日誌。以下圖:
write pos表示日誌當前記錄的位置,當ib_logfile_4寫滿後,會從ib_logfile_1從頭開始記錄;
check point表示將日誌記錄的修改寫進磁盤,完成數據落盤,數據落盤後check point會將日誌上的相關記錄擦除掉,
即write pos->check point之間的部分是redo log空着的部分,用於記錄新的記錄,check point->write pos之間是redo log待落盤的數據修改記錄。當write pos追上check point時,得先停下記錄,先推進check point向前移動,空出位置記錄新的日誌。
 
有了 redo log,當數據庫發生宕機重啓後,可經過 redo log 將未落盤的數據(check point以後的數據)恢復,保證已經提交的事務記錄不會丟失,這種能力稱爲 crash-safe。
 
4、階段提交
有了 redo log,爲何還須要 binlog 呢?先來看看 binlog 和redo log 的區別:
 
redo log
binlog
文件大小
redo log 的大小是固定的。
binlog 可經過配置參數max_binlog_size 設置每一個 binlog 文件的大小。
實現方式
redo log 是 InnoDB 引擎層實現的,並非全部引擎都有。
binlog是 Server 層實現的,全部引擎均可以使用 binlog 日誌。
記錄方式
redo log 採用循環寫的方式記錄,當寫到結尾時,會回到開頭循環寫日誌。日誌上的記錄修改落盤後,日誌會被覆蓋掉,沒法用於數據回滾/數據恢復等操做。
binlog 經過追加的方式記錄,當文件大小大於給定值後,日誌會發生滾動,以後的日誌記錄到新的文件上,不會覆蓋之前的記錄。
由 binlog 和 redo log 的區別可知:binlog 日誌只用于歸檔,只依靠 binlog 是沒有 crash-safe 能力的。但只有 redo log 也不行,由於 redo log 是InnoDB 特有的,且日誌上的記錄落盤後會被覆蓋掉。所以須要 binlog 和 redo log 兩者同時記錄,才能保證當數據庫發生宕機重啓時,數據不會丟失。
 
當執行一條 SQL 更新語句時,過程以下:
能夠看到,在「兩階段提交」階段,將 redo log 的寫入分紅了兩步:prepare 和 commit。在 redo log 狀態爲 prepare 時記錄 binlog 能夠保證兩個日誌的記錄一致。
 
5、若是數據庫誤操做, 如何執行數據恢復?
DB宕機後重啓,InnoDB 會首先去查看數據頁中的LSN的數值。這個值表明數據頁被刷新回磁盤的 LSN 的大小。而後再去查看 redo log 的 LSN 的大小。
若是數據頁中的 LSN 值大說明數據頁領先於 redo log 刷新回磁盤,不須要進行恢復。反之須要從redo log中恢復數據。
 
注:LSN 是 日誌序列號, 爲 log sequence number 的縮寫,主要用於發生 crash 時對數據進行 recovery。LSN是一個一直遞增的整型數字,表示事務寫入到日誌的字節總量。
LSN 不只只存在於重作日誌中,在每一個數據頁頭部也會有對應的 LSN 號,該 LSN 記錄當前頁最後一次修改的 LSN 號,用於在 recovery 時對比重作日誌 LSN 號決定是否對該頁進行恢復數據。
前面說的check point也是由 LSN 號記錄的,LSN 號串聯起一個事務開始到恢復的過程。
 
若是將 innodb_flush_log_at_trx_commit 和 sync_binlog 參數設置成 1,前者表示每次事務的 redo log 都直接持久化到磁盤,後者表示每次事務的 binlog 都直接持久化到磁盤,能夠雙重保證 MySQL 異常重啓以後的數據不會丟失。
相關文章
相關標籤/搜索