試用即將發行的PostgreSQL 15的人會發現少了一個後臺程序:
postgres 1710 1 0 04:03 ? 00:00:00 /usr/pgsql-15/bin/postmaster -D /var/lib/pgsql/15/data/ postgres 1711 1710 0 04:03 ? 00:00:00 postgres: logger postgres 1712 1710 0 04:03 ? 00:00:00 postgres: checkpointer postgres 1713 1710 0 04:03 ? 00:00:00 postgres: background writer postgres 1715 1710 0 04:03 ? 00:00:00 postgres: walwriter postgres 1716 1710 0 04:03 ? 00:00:00 postgres: autovacuum launcher postgres 1717 1710 0 04:03 ? 00:00:00 postgres: logical replication launcher
來和PostgreSQL 14比較一下:
postgres 1751 1 0 04:04 ? 00:00:00 /usr/pgsql-14/bin/postmaster -D /var/lib/pgsql/14/data/ postgres 1752 1751 0 04:04 ? 00:00:00 postgres: logger postgres 1754 1751 0 04:04 ? 00:00:00 postgres: checkpointer postgres 1755 1751 0 04:04 ? 00:00:00 postgres: background writer postgres 1756 1751 0 04:04 ? 00:00:00 postgres: walwriter postgres 1757 1751 0 04:04 ? 00:00:00 postgres: autovacuum launcher postgres 1758 1751 0 04:04 ? 00:00:00 postgres: stats collector postgres 1759 1751 0 04:04 ? 00:00:00 postgres: logical replication launcher
是的,stats collector程序沒有了。但是去掉這個程序是個好事,一個主要的瓶頸和令人頭疼的問題永遠消失了。
stats collector的工作內容是什麼?
新手使用者可能想知道它是什麼以及為什麼PG 14和更早版本需要它。至少會有一些使用者對用於查詢計劃的表級統計資訊的收集(ANALYZE)感到困惑。但這是不同的。PostgreSQL跟蹤每個程序的所有活動以獲得累積統計資訊,例如掃描表或索引的次數,或者最後一次vacuum或autovacuum在表上執行的時間,或者autovacuum在表上執行的次數等。所有stats collector收集的資料可通過不同的pg_stat_*檢視獲得。
問題點
由於對談的每個後端都是PostgreSQL中的一個單獨程序,因此收集統計資訊並傳輸並不是一件容易的事。每個後端將有關他們所做的活動的資訊傳送到單個"stats collector"程序。
這種通訊過去是通過UDP通訊端進行的。這種方法有很多問題,這不是一個可延伸的模型。
使用者經常報告不同型別的問題,例如:過時的統計資訊、stats collector未執行、autovacuum無法運作/啟動等。
如果stats collector在特定機器上出現問題,過去真的很難理解出了什麼問題。
"stats collector"的另一個不利影響是它引起的IO。如果啟用DEBUG級別2,可能會看到不斷出現在PostgreSQL紀錄檔中的訊息,例如:
2022-08-22 03:49:57.153 UTC [736] DEBUG: received inquiry for database 0 2022-08-22 03:49:57.153 UTC [736] DEBUG: writing stats file "pg_stat_tmp/global.stat" 2022-08-22 03:49:57.153 UTC [736] DEBUG: writing stats file "pg_stat_tmp/db_0.stat" 2022-08-22 03:49:57.168 UTC [1278] DEBUG: autovacuum: processing database "postgres" 2022-08-22 03:49:57.168 UTC [736] DEBUG: received inquiry for database 13881 2022-08-22 03:49:57.168 UTC [736] DEBUG: writing stats file "pg_stat_tmp/global.stat" 2022-08-22 03:49:57.168 UTC [736] DEBUG: writing stats file "pg_stat_tmp/db_13881.stat" 2022-08-22 03:49:57.169 UTC [736] DEBUG: writing stats file "pg_stat_tmp/db_0.stat"
這可能會導致資料目錄所在的掛載點產生大量IO。這是引數stats_temp_directory的值所指向的地方。在許多系統上,它將是資料目錄中的pg_stat_tmp。
在Ubuntu/Debian上,它將位於/var/run/postgresql中,例如:
postgres=# show stats_temp_directory ; stats_temp_directory ----------------------------------------- /var/run/postgresql/14-main.pg_stat_tmp (1 row)
PostgreSQL 15中的新特性
開始使用動態共用記憶體來收集統計資訊,而不再使用檔案和檔案系統。
以前,統計收集器通過UDP接收統計更新,並通過定期將統計資料寫入臨時檔案來共用統計資料。這些檔案可以達到數十兆位元組,並且每秒最多寫入兩次。這會阻止我們新增其他有用的統計資料。
現在統計資訊儲存在共用記憶體中。可變編號物件的統計資訊儲存在dshash雜湊表中(由動態共用記憶體支援)。固定編號的統計資訊儲存在普通共用記憶體中。
pgstat.c的標頭檔案包含該架構的概述。
不再需要統計資訊收集器,將其刪除。
現在副本刪除了已刪除物件的統計條目,從完全關閉的副本啟動時不再需要重置統計資訊。
顯然,引數stats_temp_directory不見了。因此,我們不需要pg_stat_tmp目錄,該目錄是在資料目錄(或其他位置)中,在該目錄生成和讀取所有統計檔案。然而,仍保留此目錄是因為不會破壞許多依賴於該目錄的擴充套件,例如pg_stat_statements。
在載入擴充套件庫之前,目錄保持為空。例如,如果我們載入pg_stat_statements庫,目錄中會出現一個檔案。
$ ls pg_stat_tmp/ pgss_query_texts.stat
當然,擴充套件不是免費的,他們也有對應的成本。
在新架構中,大多數統計更新首先在每個程序中本地累積為"pending"(每個backend都有一個backend本地雜湊表)。"pending"是指它們已累積但尚未提交到共用統計系統(shared stats system)。之後會在提交或超時後重新整理到共用記憶體。
由於統計資料會在有人嘗試讀取時同時被更新,因此讀取一致性就出現了。因此PostgreSQL 15引入了一個新引數:stats_fetch_consistency,它可以取三個值none、cache 或snapshot:
·"none"是最有效的。但是,將不會提供讀取一致性。但對於大多數使用來說應該沒問題。
·"cache"確保重複存取產生相同的值,這對於涉及例如自連線(self-joins)是有必要的.
·"snapshot"在互動式檢查統計資訊時很有用,但開銷更大。
預設為"cache"
如果是在共用記憶體中,重啟後如何保持呢?
在被shutdown之前,檢查點程序會將這些統計資訊寫入檔案系統,重啟後可以再次被載入。通常,如果是crash了,統計資訊就丟失了。
這一改動是否會影響我的監控/指令碼?
監控檢視pg_stat_*會繼續起作用。但是,要確保取得是stats_fetch_consistency的恰當的值。如上所述,pg_stat_tmp目錄只是為擴充套件保留的。
其它
很多人像我一樣,使用postgresql的等待事件來理解postgresql以及對談都把時間花費在哪的人。資料收集和分析工具,比如pg_gather,通過使用等待事件來分析問題。
為了更好地監控postgresql,三個新的等待事件被引入了:
·PgStatsDSA:等待統計動態共用記憶體分配器存取
·PgStatsHash:等待stats共用記憶體雜湊表存取
·PgStatsData:等待共用記憶體統計資料存取
隨著統計收集器的所有開銷及其維護的消失,其他子系統(如 autovacuum)要做的工作就更少了。
此外,經常查詢統計資訊的監控工具預計會大大減少系統負載。