盡可能改善執行個體記憶體用量偏高的情形

執行個體耗用大量記憶體或產生記憶體不足 (OOM) 的問題,是常見的問題。在記憶體使用率高的情況下執行資料庫執行個體,常會引發效能問題、停頓,甚至資料庫停機。

部分 MySQL 記憶體區塊是全域使用的。也就是說,所有查詢工作負載都會共用記憶體位置,且會一直處於占用狀態,只有在 MySQL 程序停止時才會釋出。部分記憶體區塊是根據工作階段建立,也就是說,一旦工作階段關閉,該工作階段使用的記憶體也會釋回系統。

每當 Cloud SQL 適用的 MySQL 執行個體使用大量記憶體時,Cloud SQL 都會建議您找出使用大量記憶體的查詢或程序,並釋放記憶體。MySQL 記憶體消耗量可分為三個主要部分:

  • 執行緒和處理程序記憶體用量
  • 緩衝記憶體用量
  • 快取記憶體用量

執行緒和處理程序記憶體用量

每個使用者工作階段的記憶體用量取決於該工作階段執行的查詢、緩衝區或快取,並由 MySQL 的工作階段參數控制。主要參數包括:

  • thread_stack
  • net_buffer_length
  • read_buffer_size
  • read_rnd_buffer_size
  • sort_buffer_size
  • join_buffer_size
  • max_heap_table_size
  • tmp_table_size

如果在特定時間點有 N 個查詢正在執行,則每個查詢會在工作階段中根據這些參數消耗記憶體。

緩衝記憶體用量

這部分的記憶體是所有查詢的共同部分,並由 Innodb_buffer_pool_sizeInnodb_log_buffer_sizekey_buffer_size 等參數控制。

快取記憶體用量

快取記憶體包含查詢快取,用於儲存查詢及其結果,以便在後續執行相同查詢時加快資料擷取速度。它還包含 binlog 快取,可在交易執行期間保留對二進位記錄檔所做的變更,並由 binlog_cache_size 控制。

其他記憶體用量

彙整和排序作業也會使用記憶體。如果查詢使用彙整或排序作業,這些查詢會根據 join_buffer_sizesort_buffer_size 使用記憶體。

除此之外,如果啟用效能資料表,系統會耗用記憶體。如要查看效能資料結構的記憶體用量,請使用下列查詢:

SELECT *
FROM
  performance_schema.memory_summary_global_by_event_name
WHERE EVENT_NAME LIKE 'memory/performance_schema/%';

MySQL 提供許多可用檢測工具,您可以設定這些工具,透過效能結構定義監控記憶體用量。詳情請參閱 MySQL 說明文件

大量資料插入作業的 MyISAM 相關參數為 bulk_insert_buffer_size

如要瞭解 MySQL 如何使用記憶體,請參閱 MySQL 說明文件

建議

使用 Metrics Explorer 找出記憶體用量

您可以在 Metrics Explorer 中使用 database/memory/components.usage 指標查看執行個體的記憶體用量。

如果 database/memory/components.cachedatabase/memory/components.free 的記憶體總和低於 5%,發生 OOM 事件的風險就很高。如要監控記憶體用量並避免發生 OOM 事件,建議您在 database/memory/components.usage 中設定警示政策,並將指標閾值設為 95% 以上。

下表顯示執行個體記憶體與建議的快訊門檻之間的關係:

執行個體記憶體 建議的警告門檻
最多 100 GB 95%
100 GB 至 200 GB 96%
200 GB 至 300 GB 97%
大於 300 GB 98%

計算記憶體用量

計算 MySQL 資料庫的記憶體用量上限,為 MySQL 資料庫選取合適的執行個體類型。請使用下列公式:

最大 MySQL 記憶體用量 = innodb_buffer_pool_size + innodb_additional_mem_pool_size + innodb_log_buffer_size + tmp_table_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) x max_connections)

以下是公式中使用的參數:

  • innodb_buffer_pool_size:緩衝區集區大小 (以位元組為單位),即 InnoDB 快取資料表和索引資料的記憶體區域。
  • innodb_additional_mem_pool_size:InnoDB 用來儲存資料字典資訊和其他內部資料結構的記憶體集區大小 (以位元組為單位)。
  • innodb_log_buffer_size:InnoDB 用來寫入磁碟上記錄檔的緩衝區大小 (以位元組為單位)。
  • tmp_table_size:由 MEMORY 儲存引擎 (自 MySQL 8.0.28 起為 TempTable 儲存引擎) 建立的內部記憶體內暫存資料表的最大大小。
  • Key_buffer_size:用於索引區塊的緩衝區大小。MyISAM 資料表的索引區塊會經過緩衝,並由所有執行緒共用。
  • Read_buffer_size:每個為 MyISAM 資料表執行順序掃描作業的執行緒,都會為掃描的每個資料表分配這個大小的緩衝區 (以位元組為單位)。
  • Read_rnd_buffer_size:這個變數用於從 MyISAM 資料表讀取資料、任何儲存引擎,以及多範圍讀取最佳化。
  • Sort_buffer_size:每個必須執行排序作業的工作階段都會分配這個大小的緩衝區。sort_buffer_size 並非特定儲存引擎,而是以一般方式套用最佳化。
  • Join_buffer_size:緩衝區的最小大小,用於一般索引掃描、範圍索引掃描,以及不使用索引而執行完整資料表掃描的彙整作業。
  • Max_connections:同時允許的用戶端連線數量上限。

排解記憶體用量偏高的問題

  • 執行 SHOW PROCESSLIST,查看正在耗用記憶體的查詢。它會顯示所有已連線的執行緒及其執行的 SQL 陳述式,並嘗試進行最佳化。請留意狀態和時間長度欄。

    mysql> SHOW [FULL] PROCESSLIST;
    
    
  • 請查看 BUFFER POOL AND MEMORY 部分的 SHOW ENGINE INNODB STATUS,瞭解目前的緩衝區集區和記憶體用量,以便設定緩衝區集區大小。

    mysql> SHOW ENGINE INNODB STATUS \G
    ----------------------
    BUFFER POOL AND MEMORY
    ----------------------
    Total memory allocated 398063986; in additional pool allocated 0
    Dictionary memory allocated 12056
    Buffer pool size 89129
    Free buffers 45671
    Database pages 1367
    Old database pages 0
    Modified db pages 0
    
  • 使用 MySQL 的 SHOW variables 指令檢查計數器值,即可取得臨時資料表數量、執行緒數量、資料表快取數量、髒頁、開啟資料表和緩衝區池使用情形等資訊。

    mysql> SHOW variables like 'VARIABLE_NAME'
    

套用變更

分析不同元件的記憶體用量後,請在 MySQL 資料庫中設定適當的旗標。如要在 MySQL 適用的 Cloud SQL 執行個體中變更旗標,您可以使用 Google Cloud 控制台或 gcloud CLI。如要使用 Google Cloud 控制台變更標記值,請編輯「標記」部分、選取標記,然後輸入新值。

最後,如果記憶體用量仍偏高,且您認為執行查詢和標記值已達到最佳化,請考慮增加執行個體大小,以免發生 OOM。

後續步驟