執行個體耗用大量記憶體或產生記憶體不足 (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_size
、Innodb_log_buffer_size
和 key_buffer_size
等參數控制。
快取記憶體用量
快取記憶體包含查詢快取,用於儲存查詢及其結果,以便在後續執行相同查詢時加快資料擷取速度。它還包含 binlog
快取,可在交易執行期間保留對二進位記錄檔所做的變更,並由 binlog_cache_size
控制。
其他記憶體用量
彙整和排序作業也會使用記憶體。如果查詢使用彙整或排序作業,這些查詢會根據 join_buffer_size
和 sort_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.cache
和 database/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。