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

本頁說明如何設定 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 中設定快訊,當用量在 6 小時內超過限制的 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 工作站程序為目標。在這種情況下,系統會保留郵件管理員程序,因此只需要結束所有現有的資料庫連線並執行復原作業,即可保護資料庫的完整性。如果發生這種情況,服務會中斷,資料庫也會停機。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

後續步驟