PostgreSQL/Vacuum
正如我們在 MVCC 章中所看到的,資料庫會因為 膨脹 而佔用越來越多的磁碟空間:隨著時間的推移,邏輯上刪除但物理上仍然存在的舊行版本會越來越多地出現在堆和索引檔案中。本章將解釋 SQL 命令 VACUUM 和自動執行的 Autovacuum 程序如何清理檔案,從而防止它們無限制地增長。
例項中的一個程序是 Autovacuum 守護程序。它會根據統計收集器收集的值持續監控所有資料庫的狀態,並在檢測到某些情況時啟動 Autovacuum 程序,例如:表中存在大量修改。這導致了 PostgreSQL 預期的動態行為:只有在必要時,Autovauum 才會清理檔案。此外,客戶端程序可以在任何時候發出 SQL 命令 VACUUM。DBA 會在他們識別出關鍵情況時進行互動式操作,或者在定期執行的批處理作業中啟動它。在大多數情況下,由於 Autovacuum 守護程序不斷執行,因此不需要這樣做。
用來確定哪些物理存在的行版本不再需要的中心值是 xmax,它顯示哪個事務刪除了該行。消除操作必須根據必須同時適用的幾個標準來評估它
xmax必須不為零,因為值為零表示該行版本沒有被刪除。xmax必須包含一個比所有當前執行的事務的最舊 XID 更舊的 XID。這保證了沒有現有或即將到來的事務會對該行版本進行讀或寫訪問。xmax的事務必須已提交。如果它仍在執行或被回滾,則此行版本將被視為有效(未刪除)。- 如果存在行版本屬於多個事務的情況,則需要採取更多措施。
當 vacuum 操作檢測到這樣的過時行版本時,它會將其空間標記為可供將來寫入操作使用,最佳化頁面上剩餘版本在物理上的排列方式,並刪除指向已刪除行版本的索引元組。但只有在極少數情況下(或在 VACUUM FULL 的情況下),才會將此空間釋放給作業系統。在大多數情況下,它仍然被資料庫佔用,並將被未來的 INSERT、UPDATE 或 DELETE 命令使用。因此,即使 Autovacuum 執行成功,檔案的大小也不會縮小;但它們會有更多或更大的一些“洞”,將來可以儲存資料。只有在這些“洞空間”被耗盡(每頁)之後,才需要從作業系統中申請新的磁碟空間來儲存新資料。
SQL 命令 VACUUM FULL 是這種保守行為的例外。它會在作業系統級別建立一個新檔案,將所有有效的行版本複製到該檔案中,並忽略“洞”,從而不留任何額外空間,然後刪除舊檔案。但它速度較慢,並且需要對受影響的表進行獨佔鎖。
由於 vacuum 操作通常是 I/O 密集型操作,這可能會阻礙其他活動,因此 Autovacuum 會避免批次執行許多 vacuum 操作。相反,它會執行許多小的操作,並在操作之間設定時間延遲。SQL 命令 VACUUM 會立即執行,沒有任何時間延遲。
VACUUM 以及 Autovacuum 不僅會消除 膨脹。它們還會執行其他任務,以最大程度地減少自身以及其他程序在未來進行 I/O 操作的活動。由於在大多數情況下,對頁面的昂貴物理訪問已經完成,因此可以非常有效地完成這項額外工作。其他操作包括
- 凍結:它將某些行版本標記為凍結。這意味著它們被視為永遠“有效”(可見),與 wraparound 問題無關(見後)。
- 可見性對映和空閒空間對映:它會將有關處理過的頁面狀態的資訊記錄到兩個額外的檔案中,即 可見性對映 和 空閒空間對映。
- 統計資訊:與 統計資訊收集器 相似,它會收集有關每個表的行數、值的分佈等的統計資訊,作為查詢規劃器決策的基礎。