共計 4446 個字符,預計需要花費 12 分鐘才能閱讀完成。
本篇內容主要講解“MySQL 日志的知識點有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“MySQL 日志的知識點有哪些”吧!
Mysql 的日志系統是 Mysql 保證無論何時崩潰數據都不會丟失的關鍵
眾所周知 Mysql 是持久化的數據庫, 所有的數據都是持久化到硬盤中的, 保證數據不會丟失
Mysql 保證數據不會丟失是從以下兩個方面來體現的
能夠恢復到任意時刻的數據狀態
無論在事務提交前還是提交后崩潰都能保證數據不丟失
事務過程中崩潰能夠恢復到事務提交前的狀態
事務提交后崩潰已提交的數據不會丟失
MySQL 保證以上兩個點的關鍵就是通過 undo log, redo log 和 binlog 這三個日志來實現的, 接下來將逐一介紹
undo log 回滾日志
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 重做日志
redo log 是 Mysql 的物理日志, 負責記錄某個數據頁執行了什么樣的操作
redo log 的作用
負責記錄提交的事務對數據的修改, 記錄的內容大概就是對 x 表的 y 頁 z 偏移做了 a 更新
讓 Mysql 在提交事務的時候無需等待數據持久化磁盤, 只需要將 redo log 持久化到磁盤就可以了
未清除的 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 歸檔日志
binlog 是 Mysql server 層實現的日志, 是所有引擎通用的
作用
binlog 記錄的是 mysql 原始的語句邏輯, 并且是采用追加寫入的形式記錄的, 所以可以用于恢復 mysql 在任意時刻的數據庫數據狀態
所以叫 binlog 是歸檔日志
同時 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 進程崩潰這部分寫入的數據也不會丟失, 操作系統的內核線程會負責將這部分緩存中的數據寫入磁盤
但是如果操作系統崩潰了這部分數據就丟失了
最后就是 mysql 手動調用 sync 將寫入在頁緩存中的數據持久化到硬盤, 寫入完成后數據就是持久化成功了
最后的 write 和 sync 步驟 mysql 提供了對應的參數來控制寫入策略
redo log 是通過 innodb_flush_log_at_trx_commit 來控制的
設置為 0 的時候,表示每次事務提交時都只是把 redo log 留在 redo log 的緩存中
丟失風險最大
設置為 1 的時候,表示每次事務提交時都將 redo log 直接持久化到磁盤
丟失風險最小, 但是 IO 占用大
設置為 2 的時候,表示每次事務提交時都只是把 redo log 寫到 page cache
IO 占用居中, 將寫入到磁盤這個最占用 IO 的過程交由操作系統來負責
binlog 是通過參數 sync_binlog 來控制的
sync_binlog=0 的時候,表示每次提交事務都只 write,不 fsync
sync_binlog=1 的時候,表示每次提交事務都會執行 fsync
sync_binlog=N(N 1) 的時候,表示每次提交事務都 write,但累積 N 個事務后才 fsync
兩階段日志提交
什么是兩階段日志提交
將 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 提交標志, 如果有的話事務沒有問題, 直接提交
如果 redo log 中沒有對應事務的提交標志的話會對 binlog 進行檢查
如果 binlog 完整并且帶有 commit 標志, 就會提交事務并在 redo log 后面補上 commit 標志如果 binlog 不完整就回滾事務
這里可以發現兩階段日志提交中發生了崩潰是依據 binlog 來進行標準判斷的, 原因是因為主從復制是依據 binlog 來進行的
如果對兩份日志都需要檢查完整性的話, 主庫掛掉切換到從庫的時間會變長, 以 binlog 為基準的話主庫掛了直接拿著 binlog 去從庫恢復數據即可, 無需檢查 redo log 的完整性
此外 binlog 是 Mysql Server 層的通用日志, 這也是選擇 binlog 作為基準的原因
兩階段日志提交的缺點
磁盤 IO 次數高
在提交日志的時候會有 redo log 和 binlog 對應的刷盤操作, IO 次數高
鎖競爭激烈
為了保證多個事務提交的時候日志的記錄和事務的提交順序是一致的, 會使用鎖來保證日志提交的相對順序
但是在并發量大的情況下性能會變差
組提交機制
組提交機制的作用
當有躲過事務提交的時候, 將多個事務的日志合并在一起去寫入, 減少磁盤 IO 操作
組提交機制的實現
組提交機制將 commit 過程拆分成三個過程, 對每個過程都維護了一個隊列, 并且通過鎖來保證事務的寫入順序
分成三個階段分別加鎖可以減少鎖粒度, 無需鎖住事務的整個提交過程
當隊列為空的時候第一個進入隊列的事務會成為后續進入的事務的領導者, 帶領后續事務完成接下來的階段操作
階段一 : flush 階段 : 多個事務按進入的順序將 binlog 從 cache 中寫入文件 (不刷盤)
第一個進入 flush 階段的事務會作為領導者領導后面進入的事務
領導者事務會帶領所有的事務對 redo log 進行一次 write + fsync, 也就是將 redo log 寫入磁盤, 完成 redo log 的 propare 階段
如果在這個階段 Mysql 崩潰了, 會在重啟后回滾這組事務
階段二 : sync : 對 binlog 文件做 fsync 操作 (將多個事務的 binlog 合并一起刷盤)
在 flush 階段將 binlog 寫入到 binlog 文件后, 會等待一段時間再進行刷盤, 目的是組合更多事務的 binlog 一起刷盤減少消耗
等待會有時間限制和最大事務限制, 滿足其中一個條件就會立刻對 binlog 進行刷盤
sync 階段主要負責 binlog 的組提交, 如果當前階段 Mysql 崩潰的話, 在重啟后可以通過 redo log 的刷盤記錄繼續完成事務提交
因為此時 binlog 已經完成提交了, 所以可以根據 redo log 來繼續提交事務
階段三 : commit : 對各個事務做 InnoDB 的 commit 操作
到此,相信大家對“MySQL 日志的知識點有哪些”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!