PostgreSQL的vacuum流程

T1YSL發表於2021-08-15

vacuum是一種維護過程,有助於PostgreSQL的持久執行,它的兩個主要任務是刪除死元組,以及凍結事務標識。

vacuum的作用:
1.釋放,再利用更新/刪除的行所佔據的磁碟空間。
2.更新postgresql查詢計劃中使用的統計資料。
3.防止因事務ID的重置而使非常老的資料丟失。

併發清理過程為指定的表或者資料庫中的表執行以下任務:

第一部分
1.從指定的表中依次處理每一張表,
2.獲取表上的ShareUpdateExclusiveLock鎖(該鎖允許其他事物對該表進行讀取)。
3.掃描表中的所有頁面,獲取所有的死亡元組,(死元組的列表儲存在本地記憶體的maintenance_work_mem裡)
4.如果有必要,凍結舊的元組的事務標識
5.移除指向死亡元組的索引元組
第二部分
1.移除每一頁中的死亡元組,並對每一頁內的的活元組進行碎片整理,重排本頁的活元組
2.更新已經處理的空閒空間對映(FSM)和可見性對映(VM)
PG會不斷執行這個過程直至最後一頁
第三部分
1.如果最後一個頁面沒有任何元組,則截斷最後一頁
2.更新與凍結事務標識相關的系統檢視(pg_class與pg_database)
3.釋放ShareUpdateExclusiveLock鎖
第四部分
1.更新一些統計資訊(pg_stat_all_tables等)
2.移除不必要的提交日誌檔案,移除CLOG(10版本及以後為xact)中的非必要檔案與頁面
(當更新pg_database.datfrozenxid時,會嘗試刪除不必要的CLOG)

清理過程會使用共享快取,處理過的頁面不會快取在共享快取裡。
為了移除死亡元組,清理過程有兩種模式,分別是併發清理與完整清理。清理過程刪除表檔案每個頁面中的死元組,而其他事務可以在其執行時繼續讀取該表。相反,完整清理不僅會 移除整個檔案中所有的死元組,還會對整個檔案中所有的活元組進行碎片整理。其他事務在完整清理執行時無法訪問該表。
清理過程涉及全表掃描,所以引入了可見性對映(Visibility Map,VM)來提高移除死元組的效率。

VM:每個表都有各自的可見性對映,用於儲存表檔案中每個頁面的可見性,頁面的可見性確定了每個頁面是否包含死亡元組。清理過程可以跳過沒有死亡元組的頁面。
Image.png
如圖,假設一個表包含三個頁面,第0號頁和第2號頁包含死亡元組,但是第一號頁不包含死亡元組,在可見性對映中儲存著包含死亡元組的資訊,則在清理過程中,會參考VM,跳過第一個頁面清理下邊的頁面。
每個VM 檔案字尾_vm儲存,如一個表檔案的relfilenode是2612,則VM檔案為2612_vm,VM在9.6版本做了加強,除了顯示頁面可見性,還包含了頁面中原則是否全部凍結的資訊。

Image.png

凍結過程分兩種模式:惰性模式和迫切模式。

惰性模式在開始凍結處理時,PG會計算freezelimit_txid,並凍結t_xmin小於freezelimit_txid的元組,
freezelimit_txid=(OldestXmin-vacuum_freeze_min_age)
OldestXmin是當前正在執行的事務中最早的事務標識,vacuum_freeze_min_age是一個配置引數(預設為50000000)

迫切模式 9.5版本之前會掃描所有頁以檢查表中的所有元組,更新相關的系統目錄,並在可能的情況下刪除不必要的檔案和clog頁。
滿足pg_database.datfrozenxid <(OldestXmin-vacuum_freeze_table_age)時,會觸發迫切模式,vacuum_freeze_table_age 預設值為150000000。
凍結每個表後,目標表的pg_class.relfrozenxid被更新。 在完成vacuum處理之前,必要時更新pg_database.datfrozenxid。每個pg_database.datfrozenxid列在相應的資料庫中儲存最小pg_class.relfrozenxid。
Image.png

9.6版本進行了VM與凍結過程,新VM包含了每個頁面中所有元組是否被全部凍結的資訊,在迫切模式下進行凍結處理時,可以跳過僅包含凍結元組的頁面。

帶有freeze的vacuum會強制凍結指定表中的所有事務標識,而且freezeLimit會被設定為OldestXmin而不是OldestXmin - vacuum_freezre_min_age。


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

相關文章