InnoDb存儲引擎執行流程


緩沖池 buffer pool

  • 會把一些磁盤上的數據加載到該內存當中
  • 查詢數據的時候不從磁盤查,從該內存里查

undo log

  • 邏輯日志,可以認為當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄
  • 用於數據回滾
  • 實現mvcc

redo log

  • 存儲引擎層日志
  • 物理日志(類似於“對哪個數據頁中的什么記錄,做了個什么修改”)
  • 記錄對數據做了什么修改,防止已提交事務的數據丟失。因為數據不是實時刷盤的,數據是在buffer pool當中,如果數據庫宕機了並且buffer pool中的數據還沒有刷盤,修改過的數據就丟失了,redo log解決這一問題
  • redo log buffer是redo log的緩沖區,數據做了什么修改,首先會寫入到redo log buffer中,再刷盤寫入redo log中

binlog

  • 歸檔日志,屬於mysql server層,不屬於存儲引擎層
  • 邏輯性日志(類似於“對users表中的id=10的一行數據做了更新操作,更新以后的值是什么”)

事務還沒有提交,mysql宕機了怎么辦?

  • 事務沒有提交,mysql宕機,buffer pool和redo log buffer中的數據都會丟失,數據庫返回異常,提示事務失敗
  • 磁盤上的數據沒有任何變化,不影響

redo log刷盤策略

  • 當提交事務的時候,redo log buffer里的數據會根據一定規則刷到磁盤上
  • 通過innodb_flush_log_at_trx_commit參數來配置
    • 0 提交事務的時候,不立即把 redo log buffer 里的數據刷入磁盤文件的,而是依靠 InnoDB 的主線程每秒執行一次刷新到磁盤。此時可能你提交事務了,結果 mysql 宕機了,然后此時內存里的數據全部丟失
    • 1 提交事務的時候,就必須把 redo log 從內存刷入到磁盤文件里去,只要事務提交成功,那么 redo log 就必然在磁盤里了
    • 2 提交事務的時候,把 redo 日志寫入磁盤文件對應的 os cache 緩存里去,而不是直接進入磁盤文件,可能 1 秒后才會把 os cache 里的數據寫入到磁盤文件里去。此時mysql宕機,數據不會丟失;如果機器宕機,數據會丟失

binlog刷盤策略

  • 當提交事務的時候,binlog也會刷到磁盤上去
  • 通過sync_binlog參數來配置
    • 0 默認值。事務提交后,將二進制日志寫入了操作系統緩沖,若操作系統宕機則會丟失部分二進制日志
    • 1 事務提交后,將二進制文件寫入磁盤並立即執行刷新操作,相當於是同步寫入磁盤,不經過操作系統的緩存

執行一條更新sql語句,存儲引擎執行流程

  1. 把該行數據從磁盤加載到buffer pool中
  2. 對該行數據進行加鎖
  3. 寫undo log
  4. 在buffer pool當中更新數據
  5. 把所作的修改寫入到redo log buffer當中
  6. 准備提交事務redolog刷盤
  7. 准備提交事務binlog刷盤
  8. 把binlog的文件名和位置寫入commit標記,commit標記寫入redolog中,事務才算提交成功;否則不會成功


commit標記的意義

  • redo log刷盤成功,binlog還沒刷盤,數據庫宕機,沒有commit標記寫到redo log中,事務判定為失敗。因為redolog中有這次更新日志,binlog中沒有這次更新日志,會出現數據不一致問題
  • redo log刷盤成功,binlog刷盤成功,commit標記還沒來得及寫入redo log中,數據庫宕機,同樣判定事務提交失敗
  • commit寫入redo log,才能判定事務成功;因為此時,redo log中有這次更新記錄,binlog也有這次更新記錄,redo log和binlog保持了一致

內存(buffer pool)中更新過臟數據什么時候刷盤?

  • 后台io線程有時間會把內存buffer pool中更新過的臟數據(因為更新過,和磁盤上的數據不一樣,所以叫臟數據)刷回到磁盤上,哪怕這時候mysql宕機,也沒有關系,可通過redo log和binlog恢復數據到內存中,io線程有時間再把數據刷盤


執行更新sql語句存儲引擎執行流程總結

  • 執行階段
    • 數據加載到內存,寫undo log,更新內存中數據,寫redo log buffer
  • 事務提交階段
    • redo log和binlog刷盤,commit標記寫入redo log中
  • 最后
    • 后台io線程隨機把內存中臟數據刷到磁盤上



文章和圖片參考 救火隊長mysql


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM