深刻學習MySQL 02 日誌系統:bin log,redo log,undo log

上一篇文章中,咱們瞭解了一條查詢語句的執行過程,按理說這篇應該講一條更新語句的執行過程,但這個過程比較複雜,涉及到了好幾個日誌與事物,因此先梳理一下3個重要的日誌,bin log(歸檔日誌)、redo log(重作日誌)、undo log(回滾日誌)mysql

歸納

MySQL中有六種日誌文件,分別是:重作日誌(redo log)、回滾日誌(undo log)、二進制日誌(bin log)、錯誤日誌(error log)、慢查詢日誌(slow query log)、通常查詢日誌(general log),中繼日誌(relay log)。
其中bin log和undo log與事務操做息息相關,bin log也與事務操做有必定的關係,這三種日誌,對理解MySQL中的事務操做有着重要的意義。web

接下來,分別對3種日誌作總結歸納sql

bin log

是個啥

由Mysql的Server層實現,是邏輯日誌,記錄的是sql語句的原始邏輯,好比"給 ID=2 這一行的C字段加1"數據庫

怎麼工做的

binlog會寫入指定大小的物理文件中,是追加寫入的,當前文件寫滿則會建立新的文件寫入。安全

產生:事務提交的時候,一次性將事務中的sql語句,按照必定的格式記錄到binlog中。
清理:可設置參數expire_logs_days,在生成時間超過配置的天數以後,會被自動刪除。服務器

有啥用

1.用於複製,在主從複製中,從庫利用主庫上的binlog進行重播(執行日誌中記錄的修改邏輯),實現主從同步。併發

2.用於數據庫的基於時間點的還原。svg

3種記錄模式
  • statement:基於SQL語句的模式,某些語句中含有一些函數,例如 UUID,NOW 等在複製過程可能致使數據不一致甚至出錯。函數

  • row:基於行的模式,記錄的是行的變化,很安全。可是 binlog 的磁盤佔用會比其餘兩種模式大不少,在一些大表中清除大量數據時在 binlog 中會生成不少條語句,可能致使從庫延遲變大。日誌

  • mixed:混合模式,根據語句來選用是 statement 仍是 row 模式。表結構變動使用 statement 模式來記錄,若是 SQL 語句是 update 或者 delete 語句,那麼使用row模式。

redo log

是個啥

由引擎層的InnoDB引擎實現,是物理日誌,記錄的是物理數據頁修改的信息,好比"某個數據頁上內容發生了哪些改動"

怎麼工做的

原理:當一條數據須要更新時,InnoDB會先將更新操做記錄到rodolog中,並更新到內存中,這個更新就算是完成了。InnoDB引擎會在mysql空閒時將這些更新操做更新到磁盤中(數據文件)。
(這個就是MySql常常說到的WAL技術,Write-Ahead Logging ,關鍵點是先寫日誌,再寫磁盤)

存儲:redolog是順序寫入指定大小的物理文件中的。是循環寫入的,當文件快寫滿時,會邊擦除邊刷磁盤,即擦除日誌記錄(redolog file)並將數據刷到磁盤中。

有啥用

1.提供crash-safe 能力(崩潰恢復),確保事務的持久性。
數據庫忽然崩潰,有些數據並未刷到數據文件中,當重啓MySQL數據庫,會從redolog中未刷到磁盤的數據刷到磁盤中。

2.利用WAL技術推遲物理數據頁的刷新,從而提高數據庫吞吐,有效下降了訪問時延。

undo log

是個啥

由引擎層的InnoDB引擎實現,是邏輯日誌,記錄數據修改被修改前的值,好比"把Name=‘B’ 修改成Name = ‘B2’ ,那麼undo日誌就會用來存放Name='B’的記錄"

怎麼工做的

當一條數據須要更新前,會先把修改前的記錄存儲在undolog中,若是這個修改出現異常,則會使用undo日誌來實現回滾操做,保證事務的一致性。

當事務提交以後,undo log並不能立馬被刪除,而是會被放到待清理鏈表中,待判斷沒有事物用到該版本的信息時才能夠清理相應undolog。

有啥用

保存了事務發生以前的數據的一個版本,用於回滾,同時能夠提供多版本併發控制下的讀(MVCC),也即非鎖定讀

3種日誌在事物執行過程當中的工做

分別總結很難看出在sql執行過程當中這3個日誌是如何工做的,如今咱們把它們都放到一個事務中。

user表id name1  ken2  river
BEGIN update name = 'wk' from user where id = 1update name = 'river' from user where id = 2commit

實際事物的執行順序以下:
A.將id=1的行name的值讀取到內存中
B.記錄id=1的行name=ken到undo log
C.修改name=wk
D.記錄相應數據頁的修改到redo log,並更新內存中的數據
E.將id=2的行name的值讀取到內存中
F.記錄id=2的行name=lj到undo log
G.修改name=lj
H.記錄相應數據頁的修改到redo log,並更新內存中的數據
I.記錄事務中全部SQL的邏輯操做到bin log
J.提交事務
K.MySql服務器空閒時,把redo log中的物理數據頁刷到磁盤數據文件中

1.保證原子性:更新數據前,記錄undo log,爲保證在更新數據時發生異常致使更新失敗,這時可使用undo log對數據進行回滾(回滾內存中的數據,並會在redo log中記錄回滾操做)

2.保證持久性:每更新數據後,記錄redo log,爲防止服務器忽然宕機,致使沒有把數據刷到磁盤中,每次重啓MySql服務器都會從redo log將髒頁(未能及時寫到磁盤的數據頁)刷到磁盤

3.兩階段提交,保證數據的一致性:
先寫redo log,再寫bin log,完成後才能認爲事務是完整的。從庫主要經過bin log進行同步,但若是服務器異常宕機,可能會形成主從數據不一致的狀況。

a.寫完redo log宕機,bin log還沒寫
由於兩階段提交機制,MySql會判斷redo log 和 bin log是否都完整,若是不完整,則認爲事務未提交,在從redo log 刷數據時,就不會刷未提交的事務的數據

b.在寫bin log的中途宕機
已經寫了部分的bin log,可是沒有寫完整(binlog 是否完整會有一個標識符標識),仍然認爲事務未提交。崩潰恢復和主從複製時,都不會使用未提交的數據,從而實現數據的一致性。

c.bin log寫完了,但未提交事務
兩階段提交機制認爲,只要redo log和bin log都是完整的,則能夠認爲事務提交了。

總結

本篇文章只是簡單的介紹bin log、redo log、undo log,更深層次的東西就不說了,我也不懂。但願這篇文章能幫到你理解MySql背後的事務。

 掃描二維碼,關注公衆號

相關文章
相關標籤/搜索