管理記憶體用量的最佳做法

設定及監控 Cloud SQL 執行個體的記憶體用量,有助於避免效能瓶頸、記憶體不足問題和資料庫停機。建立執行個體時,您需要選取初始記憶體大小,並可調整與記憶體相關的資料庫旗標,在 PostgreSQL 工作負載增加時,確保執行個體維持良好狀態。

PostgreSQL 將記憶體元件分為全域記憶體和本機記憶體。全域記憶體會在所有程序之間共用,用於執行查詢 (例如 shared_buffers 和 max_connections);本機記憶體則專用於各個連線 (例如 work_mem、maintenance_work_mem 和 temp_buffers)。如需其他設定考量,請參閱「一般最佳做法」和「作業指南」。

記憶體用量和標記

每當 Cloud SQL 執行個體的記憶體用量偏高時,您可能會遇到下列問題:

  • 哪個查詢或程序使用大量記憶體?
  • 記憶體設定是否足以因應資料庫活動?
  • 如何變更記憶設定?

PostgreSQL 資料庫運作時,大部分記憶體用量會發生在幾個區域:

  • 共用緩衝區:PostgreSQL 分配的共用記憶體,用於保存 read 和 write 作業的資料表資料。執行 read 作業時,系統會先將從磁碟要求的資料擷取至 RAM,再提供給用戶端。同樣地,在 PostgreSQL 中,當系統要求資料 (例如 SELECT * from emp) 時,會先從磁碟擷取資料到 shared_buffers 進行快取,然後再提供給用戶端。write 作業也會發生同樣的情況。

    共用緩衝區也是所有程序和連線的共用記憶體區域,用於資料快取、連線快取和資料操縱語言 (DML) 作業等資料庫活動。這個區域可分配的上限由 shared_buffers 旗標指定,預設值為執行個體記憶體的 33%。如果 shared_buffers 的值偏高,表示記憶體中快取的資料量偏高。

  • 查詢工作記憶體:執行查詢時,PostgreSQL 會為每項作業 (例如排序和雜湊) 分配本機記憶體。在寫入暫存磁碟檔案之前,系統可為查詢的每項作業分配的最大記憶體量,是由 work_mem 旗標設定,預設值為 4 MB。如果 work_mem 的值很高,可在記憶體中排序的資料量就會很大。
  • 維護工作記憶體:VACUUM、CREATE INDEX、ALTER TABLE 和 ADD FOREIGN KEY 等部分維護作業需要 PostgreSQL 分配的獨立本機記憶體。這些作業使用的後端程序最大量可透過 maintenance_work_mem 旗標設定,預設值為 64 MB。請注意,自動清理 worker 也會使用維護工作記憶體,且上限可由 autovacuum_work_mem 旗標覆寫。如果 maintenance_work_mem 的值很高,VACUUM 作業的執行速度就會很快。
  • 暫時緩衝區:在資料庫工作階段中使用暫存資料表時,PostgreSQL 會分配暫時緩衝區,用來存放工作階段本機暫存資料表。您可以使用 temp_buffers 旗標指定大小上限,預設值為 8 MB。
  • 資料庫連線:用戶端連線至資料庫時,PostgreSQL 會建立後端程序,為用戶端工作階段提供服務。除了執行查詢所需的記憶體外,PostgreSQL 還會分配額外記憶體,用於維護系統目錄快取和預先準備的查詢計畫等資訊。您可以使用 max_connections 旗標,設定資料庫伺服器允許的並行連線數量上限。每個閒置連線會使用約 2 MB 到 3 MB 的共用記憶體。如果 max_connections 的值較高,執行個體可以建立更多連線,但會耗用記憶體。

如需 PostgreSQL 記憶體元件的完整清單,請參閱 PostgreSQL 說明文件。如要變更或修改本節列出的旗標,請參閱「設定資料庫旗標」。

監控記憶體用量

定期在 Cloud Monitoring 中監控執行個體的記憶體,並保持在記憶體限制以下。建議您在 Cloud Monitoring 中設定快訊,在用量超過限制的 90% 達 6 小時時發出快訊。當記憶體用量持續接近上限時,這項快訊會發出警告。

此外,請監控記憶體不足事件。如要這麼做,請在 Cloud Monitoring 中為 server process .* was terminated by signal 9: Killed 訊息設定記錄指標,計算記憶體不足事件,並在每次發生這類事件時發出快訊。

如果執行個體持續超過記憶體限制的 90%,或發生記憶體不足事件,您可以增加執行個體的記憶體。或者,您也可以限制資料庫連線數量,或降低 shared_buffers、work_mem 或 max_connections 等資料庫旗標,藉此減少記憶體用量。如果調低這些旗標,可能會限制執行個體的效能。

記憶體不足

如果記憶體不足,無法處理資料庫工作負載,基礎 Linux 作業系統會使用 out-of-memory (OOM) killer 結束程序來釋出記憶體,做為最後手段。Cloud SQL 經過設定,OOM killer 只會指定 PostgreSQL worker 程序。在這種情況下,系統會保留郵件管理員程序,因此只需結束所有現有的資料庫連線,並執行復原作業,即可保護資料庫的完整性。如果發生這種情況,資料庫會出現服務中斷和停機時間。PostgreSQL 資料庫記錄中會顯示類似下列的訊息:

2021-10-24 23:34:22.265 UTC [7]: [663-1] db=,user= LOG: server process (PID 1255039) was terminated by signal 9: Killed
2021-10-24 23:34:22.265 UTC [7]: [664-1] db=,user= DETAIL: Failed process was running: SELECT * FROM tab ORDER BY col
2021-10-24 23:34:22.277 UTC [7]: [665-1] db=,user= LOG: terminating any other active server processes
2021-10-24 23:34:22.278 UTC [1255458]: [1-1] db=postgres,user=postgres WARNING: terminating connection because of crash of another server process
2021-10-24 23:34:22.278 UTC [1255458]: [2-1] db=postgres,user=postgres DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
2021-10-24 23:34:22.278 UTC [1255458]: [3-1] db=postgres,user=postgres HINT: In a moment you should be able to reconnect to the database and repeat your command.
2021-10-24 23:34:22.278 UTC [1255458]: [4-1] db=postgres,user=postgres CONTEXT: while updating tuple (27,18) in relation "tab"
...
2021-10-24 23:34:22.558 UTC [1255477]: [1-1] db=postgres,user=postgres FATAL: the database system is in recovery mode
...
2021-10-24 23:34:25.579 UTC [7]: [666-1] db=,user= LOG: all server processes terminated; reinitializing
...
2021-10-24 23:34:25.691 UTC [1255482]: [1-1] db=,user= LOG: database system was interrupted; last known up at 2021-10-24 23:31:53 UTC
2021-10-24 23:34:25.776 UTC [1255482]: [2-1] db=,user= LOG: database system was not properly shut down; automatic recovery in progress
2021-10-24 23:34:25.789 UTC [1255482]: [3-1] db=,user= LOG: redo starts at 227/AB359400
2021-10-24 23:34:38.957 UTC [1255482]: [4-1] db=,user= LOG: redo done at 229/4621F508
2021-10-24 23:34:38.959 UTC [1255482]: [5-1] db=,user= LOG: last completed transaction was at log time 2021-10-24 23:34:18.5535+00
2021-10-24 23:34:39.290 UTC [7]: [667-1] db=,user= LOG: database system is ready to accept connections

因記憶體用量過高而取消的查詢

Cloud SQL 資料庫查詢使用大量記憶體時,Cloud SQL 會主動偵測高記憶體用量,並終止執行該查詢的連線,防止記憶體不足 (OOM) 故障。這可避免資料庫因記憶體用量過高而停機。

您可以查看 PostgreSQL 資料庫記錄中的查詢記錄訊息,找出因記憶體用量過高而取消的查詢。舉例來說,取消查詢的記錄會顯示下列訊息:

(...timestamp….) [PID]:  db=postgres,user=$user_id LOG: Process [PID] received SIGTERM
(...timestamp….) [PID]:  db=postgres,user=$user_id DETAIL: Cloud SQL cancelled this query owing to its excessive memory usage which can cause the PostgreSQL instance to crash.
(...timestamp….) [PID]:  db=postgres,user=$user_id HINT:  To avoid future interruptions, consider increasing instance memory or optimizing this query.

如果資料庫使用查詢洞察,您可以查看特定查詢的詳細資料,進一步瞭解已取消的查詢。您可以使用這些記錄找出已取消的查詢,並瞭解及解決已取消查詢的根本原因,最佳化資料庫的高記憶體用量。

後續步驟