PostgreSQL DBA(20) - WAL full-page-write淺析

husthxd發表於2018-12-26

PG以page(大小預設為8K)為基本的儲存單元,但OS的存取單元(block)不一定是8k,常見的是4k,而且物理持久化儲存塊裝置扇區大小是512位元組,這些不一致的情況會導致PG page的讀寫不是原子操作,也就是說可能會出現page的部分寫問題:
在寫一個page的時候,部分寫入成功但部分寫入失敗,這時候的page中的內容是不一致的,也就是說這個page已經被損壞(corrupted page)。為了解決這個問題,PG引入了full-page-write的機制。

一、full-page-write的機制

考察以下的情況(為方便起見,省略了buffer等相關的資訊):


PostgreSQL DBA(20) - WAL full-page-write淺析
full-page-write

在T1,資料庫成功執行checkpoint;
在T2,執行DML語句,這時候相關的資料會寫入到WAL中(此處忽略了WAL buffer);
在T3,提交該事務;
在T4,bgwriter把dirty pages寫入到Data file中,但在寫入過程中機器出現故障導致Crash(如掉電等),出現了部分寫的情況。
為了應對這種情況,PG在T2寫入WAL的時候,會把出現變化的page整頁寫入到WAL中,而不僅僅是tuple data。在資料庫重啟執行恢復的時候,在Redo point開始回放WAL時,如發現XLOG Record是FPI(full-page-image),則整頁替換,通過這種機制解決了部分寫的問題。

二、full-page-write的代價

當然這種機制不是免費的,其主要的負面影響是寫放大。
由於整頁寫,不可避免的出現冗餘資料;考慮這麼一種情況:如果資料庫很繁忙,而且資料的熱點分散在不同的table上,同時checkpoint執行間隔較短,那非常多的page就會通過full-page-write寫入的WAL中,導致日誌空間快速膨脹。在極端情況下,page“滿載”(基本沒有空閒空間)的情況下更新其中一條記錄都會導致整頁寫入WAL。
關於這部分的機制和解決方案,參考資料中的《如何遏制PostgreSQL WAL的瘋狂增長》有詳細論述。

三、參考資料

Write Ahead Logging — WAL
如何遏制PostgreSQL WAL的瘋狂增長
PostgreSQL 可靠性分析 - 關於redo block原子寫

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

相關文章