縮放 PostgreSQL 觸發器
Postgres 如何觸發機制規模?
我們有一個大型 PostgreSQL 安裝,我們正在嘗試使用日誌表和 TRIGGER 實現基於事件的系統。
基本上,我們想為每個表創建一個 TRIGGER,我們希望收到 UPDATE/INSERT/DELETE 操作的通知。一旦觸發此觸發器,它將執行一個函式,該函式將簡單地將一個新行(對事件進行編碼)附加到一個日誌表中,然後我們將從外部服務輪詢該日誌表。
在全部使用 Postgres TRIGGER(s) 之前,我們想知道它們是如何擴展的:我們可以在單個 Postgres 安裝上創建多少個觸發器?它們會影響查詢性能嗎?有沒有人試過這個?
基本上,我們想為每個表創建一個 TRIGGER,我們希望收到 UPDATE/INSERT/DELETE 操作的通知。一旦觸發此觸發器,它將執行一個函式,該函式將簡單地將一個新行(對事件進行編碼)附加到一個日誌表中,然後我們將從外部服務輪詢該日誌表。
這是觸發器的標準用法。
在全部使用 Postgres TRIGGER(s) 之前,我們想知道它們是如何擴展的:我們可以在單個 Postgres 安裝上創建多少個觸發器?
如果您繼續創建它們,最終您將耗盡磁碟空間。
觸發器沒有具體限制。
PostgreSQL 限制記錄在 about page 上。
它們會影響查詢性能嗎?
這取決於觸發器類型、觸發器語言以及觸發器的作用。
BEFORE ... FOR EACH STATEMENT
一個不做任何事情的簡單 PL/PgSQL觸發器的成本幾乎為零。
FOR EACH ROW
觸發器的成本高於FOR EACH STATEMENT
觸發器。顯然,使用受影響的行數進行縮放。
AFTER
觸發器比BEFORE
觸發器更昂貴,因為它們必須排隊等待語句完成其工作,然後執行。如果隊列變大,它們不會溢出到磁碟(至少在 9.4 及更低版本中,將來可能會發生變化),因此巨大的AFTER
觸發器隊列會導致可用記憶體溢出,從而導致語句中止。在插入/更新之前修改
NEW
行的觸發器比執行 DML 的觸發器便宜。您想要的特定案例通過正在進行的增強可能會更好地執行,這可能會使其進入 PostgreSQL 9.5(如果我們幸運的話),其中
FOR EACH STATEMENT
觸發器可以看到虛擬OLD
和NEW
表。這在目前的 PostgreSQL 版本中是不可能的,因此您必須使用FOR EACH ROW
觸發器。有沒有人試過這個?
當然。這是觸發器的一個非常標準的用途,以及審計、健全性檢查等。
當任務表發生更改時,您需要研究
LISTEN
並NOTIFY
找到一種喚醒工作人員的好方法。通過避免直接從觸發器與外部系統對話,您已經在做最重要的事情。這往往會給性能和可靠性帶來問題。人們經常嘗試直接從觸發器發送郵件,這是個壞消息。
這是一個稍微遲到的答案,但它可能對未來的讀者有用
現在(在 10、11、12 版本中)我們不需要兩次儲存相同的數據(在 WAL 中由 PG 和手動)。我們可以使用 Postgre邏輯解碼機制(與邏輯複製相同)來跟踪我們數據的全部或部分更改(或將這些事件發送到像 kafka 這樣的隊列以便稍後分析)