全部產品
Search
文件中心

ApsaraDB RDS:RDS MySQL記憶體使用量問題

更新時間:Jun 19, 2024

本文介紹查看記憶體使用量情況的方式,以及各種記憶體問題的原因和解決方案。

背景資訊

執行個體記憶體使用量率和緩衝池命中率是RDS MySQL的關鍵計量。如果記憶體使用量率過高,會有記憶體耗盡風險;如果緩衝池命中率低,大量的資料頁無法命中緩衝池的資料頁,需要從磁碟讀取資料,造成I/O吞吐增加和延遲增加。

查看記憶體使用量情況

RDS管理主控台提供多種查看活躍線程的方法:

  • 監控與警示

    在控制台的監控與警示頁面,單擊標準監控頁簽,可以查看執行個體的MySQL CPU/記憶體 利用率InnoDB Buffer Pool 命中率

    記憶體使用量率快取命中率

  • 資料庫自治服務DAS

    在控制台的自治服務 > 效能趨勢頁面,單擊效能趨勢頁簽,查看MySQL CPU/記憶體 利用率InnoDB Buffer Pool 命中率情況。

    記憶體利用率快取命中率

您還可以使用performance_schema,設定相關的記憶體儀錶(instrumentation),通過記憶體佔用統計表查看記憶體佔用。詳情請參見MySQL官方文檔

  • 要在執行個體啟動時開啟記憶體檢測,您可以在控制台修改performance_schema參數,RDS MySQL5.6設定為ON,RDS MySQL5.7、8.0設定為1,設定方法請參見查看執行個體參數設定完成後重啟執行個體即生效。

  • 要在執行個體運行中開啟記憶體檢測,請執行如下命令:

    update performance_schema.setup_instruments set enabled = 'yes' where name like 'memory%';

從各個維度統計記憶體消耗的相關表如下:

  • memory_summary_by_account_by_event_name:統計指定帳號(使用者和主機群組合)的事件和事件名稱。

  • memory_summary_by_host_by_event_name:統計指定主機的事件和事件名稱。

  • memory_summary_by_thread_by_event_name:統計指定線程的事件和事件名稱。

  • memory_summary_by_user_by_event_name:統計指定使用者的事件和事件名稱。

  • memory_summary_global_by_event_name:統計指定事件名稱的事件。

RDS MySQL記憶體高常見原因

通常InnoDB Buffer Pool的記憶體佔用是最大的,Buffer Pool的記憶體佔用上限受到Buffer Pool配置參數的限制,但是還有很多記憶體是在請求執行中動態分配和調整的,例如記憶體暫存資料表消耗的記憶體、prefetch cache、table cache、雜湊索引、行鎖對象等,詳細的記憶體佔用和相關參數限制,請參見MySQL官方文檔

多語句(multiple statements)

MySQL支援將多個SQL語句用英文分號(;)分隔,然後一起發給MySQL,MySQL會逐條處理SQL,但是某些記憶體需要等到所有的SQL執行結束才釋放。

這種multiple statements的發送方式,如果一次性發送的SQL非常多,例如達到數百兆,SQL實際執行過程中各種對象分配累積消耗的記憶體非常大,很有可能導致MySQL進程記憶體耗盡。

一般情境下,如果存在大批量的multiple statements,網路流量會有突增,可以從網路流量監控和SQL洞察,判斷是否有這種現象。建議業務實現中盡量避免multiple statements的SQL發送方式。

記憶體耗盡

緩衝池(Buffer Pool)問題

所有表的資料頁都存放在緩衝池中,查詢執行的時候如果需要的資料頁直接命中緩衝池,就不會發生物理I/O,SQL執行的效率較高,緩衝池採用LRU演算法管理資料頁,所有的髒頁放到Flush List鏈表中。

RDS MySQL的InnoDB Buffer Pool大小預設設定為記憶體的75%,這部分記憶體通常是執行個體記憶體中佔比最大的。

Buffer Pool相關的常見問題:

  • 資料頁預熱不足導致查詢的延遲較高。通常發生在執行個體重啟、冷資料讀取或緩衝池命中率較低的情境,建議升級執行個體規格或大促前預熱資料。

  • 髒頁累積太多。當未重新整理髒頁的最舊LSN和當前LSN的距離超過76%時,會觸發使用者線程同步重新整理髒頁,導致執行個體效能嚴重下降。最佳化方式是均衡寫入負載、避免寫入吞吐過高、調整重新整理髒頁參數或升級執行個體規格等。

  • 高記憶體執行個體的參數innodb_buffer_pool_instances設定較小。高QPS負載情況下,緩衝池的鎖競爭會比較激烈。建議高記憶體的執行個體將參數innodb_buffer_pool_instances設定為8或16,甚至更高。

暫存資料表

記憶體暫存資料表大小受到參數tmp_table_sizemax_heap_table_size限制,超過限制後將轉化為磁碟暫存資料表,如果瞬間有大量的串連建立大量的暫存資料表,可能會造成記憶體突增。MySQL 8.0實現了新的temptable engine,所有線程分配的記憶體暫存資料表大小之和必須小於參數temptable_max_ramtemptable_max_ram預設為1 GB,超出後轉換為磁碟暫存資料表。

其他原因

如果執行個體內表特別多或QPS很高,Table Cache可能也會消耗記憶體,建議執行個體避免建立太多表或設定參數table_open_cache過大。

自適應雜湊索引佔用的記憶體預設是Bufffer Pool的1/64。如果查詢或寫入長度非常大的Blob大欄位,會對大欄位動態分配記憶體,也會造成記憶體增加。

還有非常多的原因會造成記憶體上漲,如果出現記憶體使用量率異常增加或執行個體記憶體耗盡,您可以參考MySQL官方文檔排查上漲原因。