InnoDB二階段日誌提交機制

來源:互聯網
上載者:User

InnoDB二階段日誌提交機制

前些天在查看關於innodb_flush_log_at_trx_commit的官網解釋時產生了一些疑問,關於innodb_flush_log_at_trx_commit參數的詳細解釋參見官網。

其中有一段是這麼寫的:With a value of 2, the contents of the  InnoDB log buffer are written to the log file after each transaction commit and the log file is flushed to disk approximately once per second.意思是:如果innodb_flush_log_at_trx_commit的值設為2,那麼log buffer裡的內容會在每次提交時被寫入log file,然後logfile也會被flush到disk。由於innodb的log file據我所知是在硬碟上的ib_logfile,所以對於這裡的log file被flush到disk很疑惑,難道log buffer和disk之間還存在了一層可以緩衝log file的結構? 在查閱了大量中英文資料後,總算有了初步的瞭解,暫總結於此。 一、名詞解釋在innodb儲存引擎中,有一種專屬的log file,即redo log file,因此對於innodb儲存引擎來說,就存在兩種logfile:redo log和binlog.redo log:即data目錄下的ib_logfile0,ib_logfile1(個數由innodb_log_files_in_group控制),innodb儲存引擎特有,在記憶體中有相應的redo log buffer。因此寫redo時的3層結構為:redo log buffer--->檔案系統快取中的redo logfile--->disk上的redo log filebinlog:預設在data目錄下,也可以通過log_bin參數直接指定路徑,檔案名稱為預設為<hostname>-bin首碼的檔案,在記憶體中沒有log buffer。因此寫binlog時的2層結構為:檔案系統快取中的binlog--->disk上的binlog 二、二階段日誌寫的流程當開啟binlog後,如果會話發出了commit的請求,那麼在committed之前,一系列的流程為:1.prepare階段:將log buffer的事務更改和事務commit資訊寫入檔案系統快取中的redo log file,注意log buffer和undo buffer(也叫undo page)是在事務執行過程中就即時產生的(undo預設在系統資料表空間中,5.6以後也可以自己指定獨立的資料表空間),檔案系統快取中的redo log 是否flush到disk,取決於innodb_flush_log_at_trx_commit參數。innodb_flush_log_at_trx_commit:
  • 此值為0表示:redo log buffer的內容每秒會被寫入檔案系統快取的redo log裡,同時被flush(固化)到disk上的redo log file中。
  • 此值為1表示:redo log buffer的內容會在事務commit時被寫入檔案系統快取的redo log裡,同時被flush(固化)到disk上的redo log file中。
  • 此值為2表示:redo log buffer的內容會在事務commit時被寫入檔案系統快取的redo log裡,而檔案系統快取的redo log每秒一次被flush(固化)到disk上的redo log file中。
2.寫binlog階段:此階段調用兩個方法write()和fsync(),前者負責寫檔案系統快取中的binlog,後者負責將檔案系統快取中的binlog寫入disk上的bin log,前者在此階段一定會被調用,後者的調用機制由sync_binlog參數控制。關於sync_binlog參數:
  • sync_binlog=0:表示fsync()的調用完全交給作業系統,即檔案系統快取中的binlog是否重新整理到disk完全由作業系統控制。
  • sync_binlog=1:表示在事務提交時,binlog一定會被固化到disk
  • sync_binlog=N(N>1):資料庫崩潰時,可能會丟失N-1個事務,具體原理也詳見
3.最終commit階段:此階段主要包含:server告訴儲存引擎,binlog和redo log都已寫好(至少在檔案系統快取層級已經寫好),按正常機制提交資料吧,然後向會話返回committed的確認提交資訊。 三、故障恢複解析1.如果在一階段後崩潰,那麼由於binlog未寫,資料顯然未能提交,算是失敗的交易,無需前滾或復原。(對於Oracle資料庫則情況更為複雜,有些大事務即便未提交也可能有已經固化的資料,那麼就需要進行復原。還不清楚mysql的大事務是否也有未提交資料提前寫入disk的機制)2.如果在二階段後崩潰,那麼只有一種情況可以保證資料完全不丟失,即:innodb_flush_log_at_trx_commit和sync_binlog都設定為1,此時redo log和binlog都被固化到磁碟,可以保證commit後未寫入的資料在recovery時被前滾提交。如果任意一個不為1,那麼都可能造成binlog和redo log不一致的情況,此時很可能丟失事務。因此,為保證主從完全一致,主庫的innodb_flush_log_at_trx_commit和sync_binlog都必須設定為1。 至於5.6以後的為解決並發事務提交異常而出現的3階段組提交機制,有待繼續研究。 

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.