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

本頁面說明如何設定 Cloud SQL 執行個體的記憶體用量。

簡介

建立 Cloud SQL 執行個體時,您可以為該執行個體選取記憶體容量。隨著 PostgreSQL 資料庫的工作負載增加,執行個體的記憶體用量也會增加。耗用大量記憶體的執行個體可能會造成效能瓶頸,有時會導致記憶體不足的問題。

如果 Cloud SQL 執行個體因需求增加而耗盡記憶體,可能會導致資料庫停機。因此,請務必正確設定執行個體記憶體和記憶體相關資料庫標記,並監控記憶體用量,確保執行個體能以正常狀態運作。

PostgreSQL 記憶體元件大致分為兩個部分:

  • 全域記憶體:這是在執行查詢時,會在所有程序中共用的記憶體,例如 shared_buffersmax_connections
  • 本機記憶體:這是指派給每個連線的專屬記憶體,例如 work_memmaintenance_work_memtemp_buffers

如需其他設定注意事項,請參閱「一般最佳做法」和「操作指南」。

記憶體用量和標記

每當 Cloud SQL 執行個體的記憶體用量過高時,可能會出現下列問題:

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

PostgreSQL 資料庫運作時,大部分的記憶體用量都會出現在以下幾個區域:

  • 共用緩衝區:這是 PostgreSQL 分配的共用記憶體,用於儲存 readwrite 作業的資料表資料。對於 read 作業,從磁碟要求的任何資料都會先擷取到 RAM,然後再提供給用戶端。同樣地,在 PostgreSQL 中,當系統要求資料 (例如 SELECT * from emp) 時,系統會先從磁碟擷取資料,並將其提供給 shared_buffers 進行快取,write 運算也是如此。

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

  • 查詢工作記憶體:在執行查詢時,PostgreSQL 會為每項作業 (例如排序和雜湊) 分配本機記憶體。work_mem 標記會設定查詢的每項作業可分配的最大空間,以便在寫入暫時磁碟檔案之前使用,預設值為 4 MB。如果 work_mem 的值偏高,表示記憶體中可排序的資料量偏高。
  • 維護工作記憶體:某些維護作業 (例如 VACUUMCREATE INDEXALTER TABLEADD FOREIGN KEY) 需要 PostgreSQL 分配的個別本機記憶體。這些作業使用的後端程序最大容量可透過 maintenance_work_mem 標記設定,預設值為 64 MB。請注意,自動清除工作站也會使用維護工作記憶體,且最大值可由 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% 時發出警示。當記憶體用量持續接近上限時,系統會發出這項快訊警告。

此外,請監控記憶體不足事件。為此,請在 Cloud Monitoring 中為 server process .* was terminated by signal 9: Killed 訊息設定以記錄為基礎的指標,以便計算記憶體不足事件的數量,並在發生這類事件時發出快訊通知。

如果執行個體的運作情形持續超過記憶體限制的 90%,或是發生記憶體不足事件,您可以增加執行個體的記憶體。或者,您也可以限制資料庫連線數量,或降低 shared_bufferswork_memmax_connections 等資料庫標記,以減少記憶體用量。降低這些標記可能會限制執行個體的效能。

記憶體不足

當記憶體不足以處理資料庫工作負載時,為最後手段,基礎 Linux 作業系統會使用 out-of-memory (OOM) killer 終止程序來釋放記憶體。設定 Cloud SQL 後,OOM killer 就會只針對 PostgreSQL 工作者程序進行設定。在這種情況下,Postmaster 程序會保留,因此只需結束所有現有的資料庫連線,並執行復原作業,即可保護資料庫的完整性。在這種情況下,資料庫可能會出現服務中斷和停機的情形。在 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

後續步驟