mysql checkpoint

guocun09發表於2020-09-15

MySQL innodb Checkpoint的設計和Oracle checkpoint類似,主要是為了縮短資料庫恢復時間,buffer pool不夠用時刷髒頁到datafile,保證redo log file的迴圈使用而不會一直增大。

MySQL innodb引擎透過LSN(Log Sequence Number)來標記版本,透過show engine innodb status \G輸出做解釋:

---

LOG

---

Log sequence number 2722769  #LSN1,當前資料庫系統LSN,最新事務的LSN

Log flushed up to   2722769  #LSN2,當前已寫入redo log file的LSN

Pages flushed up to 2722769  #LSN3,當前最舊髒頁資料對應的LSN

Last checkpoint at  2722760  #LSN4,當前已寫入redo log file checkpoint的LSN

0 pending log flushes, 0 pending chkp writes

129 log i/o's done, 0.00 log i/o's/second

----------------------

LSN1>=LSN2>=LSN3>=LSN4



檢查點分為:

sharp checkpoint全量檢查點 在資料庫關閉時將髒頁重新整理到datafile ,透過引數innodb_fast_shutdown=1 或 0可以實現

Innodb_fast_shutdown告訴innodb在它關閉的時候該做什麼工作。有三個值可以選擇:
0表示在innodb關閉的時候,需要purge all, merge insert buffer,flush dirty pages。這是最慢的一種關閉方式,但是restart的時候也是最快的。
1表示在innodb關閉的時候,它不需要purge all,merge insert buffer,只需要flush dirty page。1是預設值。
2表示在innodb關閉的時候,它不需要purge all,merge insert buffer,也不進行flush dirty page,只將log buffer裡面的日誌flush到log files。因此等下進行恢復的時候它是最耗時的。

purge all,merge insert buffer的含義:

Purge all  這個操作主要是刪除那些無用的undo頁。對於delete操作,innodb是透過先將要刪除的那一行標記為刪除,而不是馬上清除這一行,因為innodb實現了MVCC,這些undo段用來實現MVCC機制。MVCC也就是常說的多版本控制,鎖不阻塞讀,讀也不阻塞寫,這樣大大提高了併發性。那麼在一致性讀的時候,怎麼才能找到和事務開始的那個版本呢?對於主鍵索引,每個行都有一個事務ID和一個undo ID,這個undo ID指向了這行的先前版本的位置。對於非主鍵索引,也就是常說的secondary index,是透過先找主鍵索引再找到undo段。而對於update操作,則是先標記刪除,然後insert一個新的行,接下來如果有一致性讀,那麼查詢old version的行的原理和delete操作是一樣的,詳情見[1]。現在接著說purge all操作,隨著DML的操作越來越多,那麼回滾段必然也會越來越多導致佔用了許多磁碟空間,那麼innodb就會定期刪除一些無用的undo頁,首先,innodb重啟的時候必然undo頁都會無效所以會進行purge all操作,另外,隨著時間的推移必然一些事務已經完成,它們已不再需要某些undo頁,那麼這些undo在mysqld running的時候也會定期的進行清除。
Merge insert buffer  Insert buffer是innodb的一個特性之一,在非聚簇、且不是唯一索引(即非主鍵索引、非唯一索引)的情況下,如果插入的索引行所屬的頁在buffer pool中就直接更新這個頁,否則它會將這個索引行插入到insert buffer中,然後定期對這個insert buffer進行合併(合併的本質工作就是將insert buffer中的資訊更新到真正的索引檔案中去)。因為innodb的secondary index是非聚簇的,那麼插入很有可能帶來大量的隨機I/O,而如果利用insert buffer對一些屬於相同頁的行進行合併,那麼就會減少隨機IO從而提高效能。但是這裡需要注意的是,insert buffer和doublewrite buffer是類似的概念,他實際上屬於system tablespace中的一部分[2],正由於它也是持久化儲存,那麼在伺服器當機或是重啟之後這些資訊不會丟失,所以也就有了在前面介紹innodb_fast_shutdown時所說:在innodb重啟時,可能需要進行merge insert buffer。那麼在什麼情況下需要對insert buffer進行merge操作呢?
a>     在innodb restart的時候
b>     master thread會定期的進行merge操作
c>       每次讀取secondary index page時,如果所需頁不在buffer pool,而這些頁在insert buffer中的時候,這時需要先對insert buffer進行合併,然後才能被讀取。為什麼這樣呢?因為所有插入的索引行所屬的頁如果不在buffer pool中,而又在insert buffer中,那麼它一定代表了頁的最新狀態(不理解?因為每次插入索引行的時候,如果所需頁不在
buffer pool中就直接插入到insert buffer中,而一旦insert buffer merge後相關的行也就不在insert buffer更新secondary index page了)。這時或許你會問那麼為什麼不直接讀取insert buffer中的頁然後繼續操作而一定要合併(更新到索引檔案)呢?因為在innodb中是資料檔案(也就是主鍵索引)和索引檔案快取的,在insert buffer中讀取了需要的頁後,那麼必然就會在buffer pool中快取了這個頁,而如果這個頁還留在insert buffer中卻不更新到secondary index page去,那麼,第一,這將不能保證索引檔案得到更新;第二,insert buffer的空間會被佔用。而如果這一步將insert buffer 合併後,不但減小了insert buffer的使用空間,而且將這merge操作完成了一部分,減小了以後merge的負擔(不是有句話叫做今日事今日畢麼),不過這也減慢了讀的操作,因為讀操作必須等待這個頁的合併。


fuzzy checkpoint 部分頁重新整理檢查點,主要4類:

1.master thread checkpoint 

master thread週期性從cache pool的髒頁列表種重新整理一定比例的頁到datafile,相關引數:innodb_io_capacity

2.FLUSH_LRU_LIST checkpoint

page cleaner thread透過innodb_lru_scan_depth數量重新整理髒頁

3.async/sync flush checkpoint

redo log file不可用時,強制將一些髒頁重新整理到datafile。sync位置時redo log的7/8處,async是redo log的3/4處

4.dirty page too much

buffer log髒頁太多,達到innodb_max_dirty_pages_pct時強制進行checkpoint


參考:

https://blog.csdn.net/zbszhangbosen/article/details/7434093

https://www.cnblogs.com/chenpingzhao/p/5107480.html

MySQL DBA工作筆記

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25583515/viewspace-2721160/,如需轉載,請註明出處,否則將追究法律責任。

相關文章