這篇文章為大家帶來了關於mysql的相關知識,其中主要介紹了關於日誌的相關問題,Mysql的日誌系統是Mysql保證無論何時崩潰資料都不會遺失的關鍵,下面一起來看一下,希望對大家有幫助。
推薦學習:mysql影片教學
#Mysql的日誌系統是Mysql保證無論何時崩潰資料都不會遺失的關鍵
眾所周知Mysql是持久化的資料庫, 所有的資料都是持久化到硬碟中的, 保證資料不會遺失
Mysql保證資料不會遺失是從以下兩個方面來體現的
能夠恢復到任意時刻的資料狀態
無論在交易提交前或提交後崩潰都能保證資料不會遺失
事務過程中崩潰能夠恢復到交易提交前的狀態
交易提交後崩潰已提交的資料不會遺失
MySQL保證以上兩個點的關鍵就是透過undo log, redo log 和binlog 這三個日誌來實現的, 接下來將逐一介紹
undo log是Mysql的回滾日誌, 儲存的是舊版的資料
#主要作用
儲存舊版的資料
# 配合Read View和隱藏欄位實作了Mysql的快照讀取
用於在交易執行失敗的時候回滾到事務開始前的版本
undo log 有什麼型別
undo log 有兩種類型
對於insert 指令, undo log 記錄的是新增的記錄的主鍵, 在回滾的時候根據undo log 中的主鍵去刪除對應的記錄即可
對於update / delete 指令, undo log 記錄的是被修改的記錄的舊資料
Mysql中的每一行資料都有一個最新修改目前資料行的事務id和回滾指標這兩個欄位, 當對資料行進行修改之後, undo log指標就會指向舊的這一行資料, 而新產生的這一行資料的回滾指標就會指向undo log指標目前指向的舊資料行
Mysql為了避免undo log指標修改指向的時候出現並發問題, 在修改之前會對undo log指標增加排他鎖以保證undo log的正確寫入
undo log 什麼時候刪除
undo log是用來保證事務在未提交的時候可以順利回滾到事務開始前的狀態, 當事務提交之後undo log就失去作用了, 就需要被刪除
undo log是交由Mysql中的Purage 線程來負責刪除的, purage會定期檢查undo log中的deleted_bit 標誌, 這個標誌會在事務提交後被設定為true, purage 執行緒發現為true的記錄就會負責將其刪除
redo log是Mysql的實體日誌, 負責記錄某個資料頁執行了什麼樣的動作
redo log 的作用
負責記錄提交的事務對資料的修改, 記錄的內容大概就是對x表的y頁z偏移做了a更新
#讓Mysql在提交交易的時候無需等待資料持久化磁碟, 只需要將redo log持久化到磁碟就可以了
未清除的redo log的數量標識了未刷盤的髒頁數量
持久化資料到磁碟是隨機IO過程, 所以Mysql選擇將資料快取起來, 等待一個適當的時機將資料一次寫入磁碟, 減少IO
但是資料快取在記憶體中有遺失的風險, 所以Mysql選擇將redo log持久化
redo log是順序寫, 持久化的效率比隨機寫的效率要高, 並且redo log記錄了數據的變化情況, 只要redo log在就可以保證在Mysql重啟後恢復數據
#在InnoDB中, redo log是一個固定大小的類似循環隊列的存在, 每次寫入都從後面write pos的位置, 在持久化數據的時候就移動check point往前讀取
#這樣設計的原因是因為redo log是防止Mysql崩潰後快取的髒頁資料遺失而存在的
當Mysql中的資料持久化到磁碟中後, 被持久化部分的redo log其實就沒有用了, 就可以騰出空間來記錄新的數據
undo log 和redo log 的區別
#undo log記錄的是交易執行過程中舊資料的狀態, redo log記錄的是資料更新之後的狀態
redo log其實保障的是交易的持久性和一致性,而undo log則保障了交易的原子性
binlog是Mysql server層實作的日誌, 是所有引擎通用的
作用
binlog記錄的是mysql原始的語句邏輯, 並且是採用追加寫入的形式記錄的, 所以可以用來恢復mysql在任意時刻的資料庫資料狀態
同時binlog也是Mysql實作主從複製的依賴, 從函式庫透過從主函式庫複製binlog回放來同步主函式庫的資料狀態
#定義
先寫日誌到磁碟中, 再寫資料到磁碟中Mysql的寫操作不是立刻寫入到磁碟中的, 而是先寫日誌, 保證redo log和binlog都持久化到磁碟中再由後台執行緒選擇時機將資料持久化到硬碟的
為什麼要先寫日誌到磁碟中
##因為刷髒頁是一個隨機讀寫的過程, 持久化到磁碟中的速度肯定沒有redo log | binlog這些順序寫的速度快, 所以選擇先在內存中對數據進行修改, 再後期選擇時機異步持久化到磁碟中所以在髒頁還未刷入磁碟中的這段時間就由redo log | binlog來保證數據的持久化, 防止斷電重啟等情況內存中的數據遺失當髒頁滿的時候需要將髒頁寫入到磁碟再淘汰, 為何不全部淘汰掉下次使用的時候再透過redo log來復原呢從效能方面考慮的, 如果每次從磁碟中讀取資料到記憶體都需要和redo log比對更新, 效率很低MySQL刷髒頁寫入到磁碟保證了資料頁只要在內存中, 就肯定是當前最新的數據可以返回如果內存中沒有數據只要從磁碟中讀取肯定能得到最新的正確數據, 而不用再去同redo log進行比對binlog和redo log的寫入程序- WAL機制的基本保證binlog和redo log都是將日誌寫入分割成三個程序寫入cache, write和sync#在交易執行過程中會將binlog和redo log寫入到對應分配的快取中, 以便在交易提交的時候一次性寫入到磁碟中在交易提交的時候會先進行write將資料寫入到作業系統的頁快取中, 此時資料還未真正寫入檔案, 但是已經是交由作業系統的快取來保管了, 如果此時Mysql進程崩潰這部分寫入的資料也不會遺失, 作業系統的核心執行緒會負責將這部分快取中的資料寫入磁碟
最後的write和sync步驟mysql提供了對應的參數來控制寫入策略redo log是透過innodb_flush_log_at_trx_commit來控制的
#什麼是兩階段日誌提交
將redo log日誌提交的過程分為prepare和commit這兩個階段, binlog日誌提交在這兩個階段中間交易提交時redo log先提交後進入prepare狀態,然後binlog提交完成後redo log才能將日誌的狀態修改為commit已提交
為什麼需要兩階段日誌提交和InnoDB引擎的回滾機制有關, InnoDB的redo log提交了事務就無法回滾了, 如果在redo log提交後binlog寫入失敗的話就會出現兩份不統一的情況如果此時資料庫異常重啟的話要依據那一份來恢復資料就值得思考了, 所以才需要兩階段日誌提交
假設現在在時刻A資料庫崩潰的話, 因為binlog還未寫入, redo log還未提交, 所以重啟後事務會回滾, 兩份日誌依舊是統一狀態
如果是時間段B的話, 就需要對redo log的提交標誌進行判斷了, 在查詢redo log中是否有commit提交標誌, 如果有的話事務沒有問題, 直接提交
兩階段日誌提交的缺點
群組提交機制
群組提交機制的作用
當有躲過交易提交的時候, 將多個交易的日誌合併在一起去寫入, 減少磁碟IO操作#群組提交機制的實作
群組提交機制將commit流程拆分成三個流程, 對每個流程都維護了一個佇列, 並且透過鎖定來保證交易的寫入順序flush階段 : 多個事務按進入的順序將binlog從cache中寫入文件(不刷盤)
sync : 對binlog檔案做fsync作業(將多個交易的binlog合併一起刷盤)
commit : 對各個事務做InnoDB的commit操作
以上是一文貫通MySQL日誌的詳細內容。更多資訊請關注PHP中文網其他相關文章!