1. 程式人生 > 其它 >48.Mysql中的checkpoint機制

48.Mysql中的checkpoint機制

1.checkpoint機制的作用:

  • Mysql在進行增刪改除的時候,是通過將資料頁從磁碟上載入到buffer_pool中(記憶體),當Mysql對資料頁進行了DML操作後,為了提高效能,減少磁碟I/O的次數,這時會設定一個刷髒頁的策略:例如master thread checkpoint
  • 為了防止記憶體中修改的髒頁消失,Mysql引入了一個redolog日誌,redolog日誌最大的作用是1是保證binlog能安全落盤,2是能減少mysql資料庫故障恢復時間
  • 說回正題,關於checkpoint的總結是:按照一定的條件將記憶體中的髒頁刷到磁碟上。

2.LSN

  LSN全稱:Log Sequence Number :日誌序列號,該序列號是一個不斷增大的數字,主要存在於資料頁、buffer_pool、redolog_buffer、redologfile中

  8.0.12版本

Log sequence number          93440256   
Log buffer assigned up to    93440256
Log buffer completed up to   93440256
Log written up to            93440256
Log flushed up to            93440256
Added dirty pages up to      93440256
Pages flushed up to          93440256
Last checkpoint at           93440256
18 log i/o's done, 0.25 log i/o's/second

  5.7.26版本

LOG
---
Log sequence number 4033522
Log flushed up to   4033522
Pages flushed up to 4033522
Last checkpoint at  4033513
0 pending log flushes, 0 pending chkp writes
10685 log i/o's done, 0.00 log i/o's/second
  Log sequence number:表示當前redo log(in buffer)中的LSN
  log flushed up to : 表示刷到redo log file on disk中的LSN
  pages flushed up to :表示已經重新整理到磁碟資料頁上的LSN
  last checkpoint at :上一次檢查點所在的位置LSN

3.我們來說說LSN具體是怎麼產生的?
  1.首先修改記憶體中資料頁時,在修改後的資料頁中記錄一個LSN號,暫時稱為:data_in_buffer_lsn
  2.在修改記憶體中資料頁的同時,redo_log_buffer(也是一塊記憶體區域,在buffer_pool中)中同時也會記錄修改的物理變化,發生變化會產生redo log,這時會記錄redo log 的一個LSN,注意這個LSN是在記憶體中,暫時稱為:redo_log_in_buffer_lsn
  3.當日志寫了部分後會觸發一個日誌落盤策略,該策略是由引數:innodb_flush_log_at_trx_commit控制,該引數在前面的內容有介紹,當將redo_log_buffer中redo log日誌刷到磁碟上後,此時在redo log日誌也會記錄一個LSN(該LSN此時在磁碟上),這個操作也是我們經常說的WAL機制,就是日誌優先寫機制,該機制是用來防止mysql在未經進行刷髒頁時出現宕機,可以用redolog file 來進行恢復。暫時稱為:redo_log_on_disk_lsn;
  4.我們在記憶體中修改的資料頁不可能一直在記憶體中,這時我們的豬腳出現(checkpoint機制),它就表示在一定的條件下將髒頁(資料髒頁和日誌髒頁)刷到磁碟上,當髒頁刷到磁碟後,所以會在本次checkpoint刷頁結束後,在redo log中記錄checkpoint的LSN位置,暫且稱之為checkpoint_lsn。
  5.要記錄checkpoint所在位置很快,只需要設定一個標誌即可,但是刷資料頁並不一定很快,比如一次性刷的資料頁非常多,也就是說要刷入的資料頁需要一定的時間來完成,中途刷入的每個資料頁都會記錄當前頁所在的LSN,暫時稱為data_page_on_disk_lsn

  上邊表示假如在12:00:00刻將所有的髒頁(資料頁髒頁和日誌髒頁)刷到磁碟後,這時檢視LSN的值是一致的,假如此時開啟了一個事務,並執行了update操作,此時發現data_in_buffer_lsn和redo_log_in_buffer_lsn增大,此時用show engine innodb status命令可以發現有如下關係:

log sequence number >log flushed up to LSN=Pages flushed up to LSN =Last checkpoint at LSN

之後再執行一個deleter語句,可以發現data_in_buffer_lsn和redo_log_in_buffer_lsn又增大了,等到12:00:01時,觸發redolog的一個刷盤規則(innodb_flush_at_timeout控制的預設日誌刷盤頻率為1s)

這時再用show engine innodb status命令可以發現有如下關係:

log sequence number LSN =log flushed up to LSN > pages flush up to LSN = last checkpoint at LSN

之後再執行一個update操作,此時可以發現data_in_buffer_lsn和redo_log_in_buffer_lsn繼續增大,此時為:LSN=300,假設此時突然出現checkpoint檢查點,即圖中④的位置,checkepoint檢查點會觸發記憶體中的髒頁和relog log日誌進行刷盤,但是由於刷盤需要一定的時間,所以資料頁刷盤還未完成時,檢查點的LSN還是上一次檢查點的LSN,但此時磁碟上資料頁和日誌頁的LSN已經增長了,即:

log sequence number LSN >log flushed up to LSN 和 pages flush up to LSN > last checkpoint at LSN

這裡log flushed up to 和pages flush up to 的大小無法確定,因為日誌刷盤可能快於資料刷盤,也可能等於,還可能是慢於,但是checkpoint機制有保護資料刷盤速度是慢於日誌刷盤的:當資料刷盤速度超過日誌刷盤時,將會暫時停止資料刷盤,等待日誌刷盤進度超過資料刷盤。

等到資料頁和日誌頁刷盤完畢,即到了位置⑤的時候,所有的LSN都等於300。

隨著時間的推移到了12:00:02,即圖中位置⑥,又觸發了日誌刷盤的規則,但此時buffer中的日誌LSN和磁碟中的日誌LSN是一致的,所以不執行日誌刷盤,所以此時用命令show engine innodb status命令檢視發現他們的LSN都相等。

隨後又執行了一個insert 語句,假設buffer中的LSN增長到了800,即圖中位置⑦。此時各種LSN的大小和位置①時一樣。隨後執行了提交動作,即位置⑧。預設情況下,提交動作會觸發日誌刷盤,但不會觸發資料刷盤,所以show engine innodb status發現:

log sequence number = log flushed up to > pages flushed up to = last checkpoint at

最後隨著時間的推移,檢查點再次出現,即圖中位置⑨。但是這次檢查點不會觸發日誌刷盤,因為日誌的LSN在檢查點出現之前已經同步了。假設這次資料刷盤速度極快,快到一瞬間內完成而無法捕捉到狀態的變化,這時用show engine innodb status檢視發現:它們各個LSN值都相等了。