Postgresql vacuum最佳實踐

Postgresql作爲世界上最先進的HTAP數據庫,以其超高在線事務處理及分析性能和強大的功能被廣泛應用與各行各業中。但其實它也並不完美,說到postgres,不得不提那個讓人一直頭疼的問題,也是數據庫使用者鎖詬病最多的地方:vacuum。那麼爲什麼會有vacuum這個東西呢?它是做什麼用的呢?

 

我們先來聊聊postgresql的mvcc機制,我們知道,postgresql是沒有undo表空間的,它通過數據的多版本來實現mvcc,一條數據的delete並不會釋放數據佔用空間,同理update是通過delete+insert的方式實現,通過這種方式減少了鎖的使用,提高了併發性能。但是這種設計天然帶來一個問題:舊數據的清理,如果清理不及時就會造成數據膨脹,這也是在頻繁更新的oltp系統中數據膨脹問題的原因。

 

這裏面其實還有一個問題,postgresql從設計之初事務號就是32位。但是32位的事務id最大隻有49億,49億的事務號在如今的生產系統中幾乎會很快耗盡,而事務號耗盡後從頭開始循環使用,這裏爲了保證數據不丟失,需要對舊的事務號進行清理,這個清理過程會使得整個數據庫無法處理新的請求,這就是網上經常所說pg的“凍結炸彈”。其實真正的清理並不是達到49億就開始的,因爲事務號是循環的,所以當達到事務號一半的時候數據庫就會出現凍結炸彈。這個凍結的問題是pg永遠繞不過去的痛。其實pg經過這麼多年的社區發展,到今天pg12版本依然是32位的事務id,這個設計有人說是爲了使得事務的回滾更快,能夠更快的尋址,但是我個人覺得犧牲大於收益。

 

而我們今天所講的主角就是解決上面兩個問題的。Vacuum的第一個功能是清理舊的數據,第二是清理舊的txid。那麼如何控制vacuum的頻率、消耗io資源的大小等就成了運維好pg數據庫非常關鍵的因素,下面我們來探討和vacuum相關的一些參數。

 

autovacuum相關參數

 

①autovacuum

表示是否自動清理功能,默認值on。

②log_autovacuum_min_duration

表示當vacuum超過多少ms後,將本次vacuum過程記錄到日誌中,默認值-1,表示不進行記錄,設置爲0代表所有vacuum都進行記錄,生產中按照實際需要開啓或者關閉。

③autovacuum_max_workers

表示執行vacuum的進程數,默認值3,對於頻繁更新的系統可以調大,5-10都是可以的。該參數重啓生效。

④autovacuum_naptime

設置兩次vacuum的時間間隔。默認值1min。

⑤autovacuum_vacuum_threshold

表示某個表更新或刪除多少條記錄後觸發vacuum,默認值50。

⑥autovacuum_analyze_threshold

表示某個表更新或刪除多少條記錄後觸發analzye,默認值50。

⑦autovacuum_work_mem

每個vacuum進程所能使用的最大內存,默認值-1,該參數就會使用maintenance_work_mem的值。

⑧autovacuum_vacuum_scale_factor

執行vacuum的閾值因子,當更新的元組數超過table_size*autovacuum_vacuum_scale_factor+autovacuum_vacuum_threshold的值時,執行vacuum操作

⑨autovacuum_analyze_scale_factor

執行analyze的閾值因子,當更新的元組數超過table_size*autovacuum_anzlyze_scale_factor+autovacuum_analyze_threshold的值時,執行analyze操作

⑩autovacuum_freeze_max_age

設置事務凍結清理的最大事務age,默認值是2億,建議增大,因爲freeze vacuum的代價太大,即使沒達到凍結的年齡,系統也會自動調用autovacuum來進行清理。該參數重啓生效。

⑪autovacuum_vacuum_cost_delay

Vacuum執行時如果達到io_limits時sleep的時間。默認值爲20ms,這個值可以調到10ms,如果發現資源負載較高,可以繼續上調autovacuum_vacuum_cost_limit值,因爲這樣系統會更加平穩,vacuum對系統的影響能夠更平均地分配到時間軸上。如果設置爲-1,會取vacuum_cost_delay值。

⑫autovacuum_vacuum_cost_limit

設置在自動VACUUM操作裏使用的開銷延遲數值。當vacuum使用的io資源超過該值限制時會sleep autovacuum_vacuum_cost_delay參數定義的時間,用來減輕vacuum對系統io的影響。默認值-1,表示不限制,建議進行設置,對於普通硬盤設置爲1000,對於ssd可以設置爲10000。

 

基於開銷的延遲清理

 

這個話題其實上面已經介紹的差不多了,因爲vacuum是一個比較消耗io資源的動作,但是有時候其實並不需要vacuum動作迅速完成,以減輕vacuum對數據庫正常業務的影響,這是pg提供了一種基於開銷的延遲清理,能夠將vacuum的時間拉長,使得io負載更輕,同時更加平穩。

 

但是指的注意的是,有時候有些清理操作會持有關鍵的鎖,這時候我們可能希望vacuum迅速結束並釋放鎖。在這種情況下,上面所說的基於延遲的清理可能不會起作用,因此執行vacuum過程中累計的cost可能遠遠大於指定的limit值。爲了避免這種情況下的長延時,真實的delay會用下面的兩者計算的較大值:

vacuum_cost_delay*accumulated_balance/vacuum_cost_limit

vacuum_cost_delay*4

 

基於開銷的延遲清理主要由以下幾個參數控制,當然如果autovacuum相關參數開啓後,會以那個爲準。

 

①vacuum_cost_delay

達到io_limits後sleep的時間

②vacuum_cost_page_hit

清理一個在共享緩存裏找到的緩衝區的預計開銷。它代表鎖住緩衝池,查找共享的散列表以及掃描頁面的內容的開銷。缺省值是1,說明vacuum命中buffer cache的開銷爲1。

③vacuum_cost_page_miss

和上面的參數類似,此參數表示vacuum沒有命中緩衝區而從磁盤上讀取數據庫並掃描的開銷,默認值爲10。

④vacuum_cost_page_dirty

修改一個原先是乾淨的塊的預計vacuum開銷。他代表把一個髒的磁盤塊再次刷新到磁盤上的額外開銷。默認值20。

⑤vacuum_cost_limit

Vacuum達到的io限制進行sleep。

 

Vacuum作爲postgresql數據庫非常獨特也是很容易出現問題的地方,非常值得我們關注。32位事務id和數據膨脹問題一直是pg的主要痛點,也是永遠繞不過去的話題,可能遭人詬病,但是在目前的版本里我們更應該關注怎樣更好的管理好它,避免那些別人踩過的坑,讓它更好的爲我們服務。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章