全部產品
Search
文件中心

ApsaraDB RDS:RDS MySQL實際記憶體配置情況

更新時間:Oct 13, 2024

RDS MySQL執行個體的記憶體是重要的績效參數,常常出現由於異常的SQL請求以及待最佳化的資料庫導致記憶體利用率升高的情況,嚴重時還會出現由於OOM導致執行個體發生HA切換的情況。RDS MySQL執行個體的記憶體可以分為共用記憶體和session私人記憶體兩部分,本文將詳細介紹各部分的構成。

記憶體共用

執行如下命令,即可查詢樣本的共用記憶體配置情況:

show variables where variable_name in (
'innodb_buffer_pool_size','innodb_log_buffer_size','innodb_additional_mem_pool_size','key_buffer_size','query_cache_size'
);
        

如下是記憶體規格為240 MB的RDS MySQL執行個體的共用記憶體配置情況的查詢結果:

+---------------------------------+-----------------+
| Variable_name                   | Value           |
+---------------------------------+-----------------+
| innodb_additional_mem_pool_size | 2097152         |
| innodb_buffer_pool_size         | 67108864        |
| innodb_log_buffer_size          | 1048576         |
| key_buffer_size                 | 16777216        |
| query_cache_size                | 0               |
+---------------------------------+-----------------+
共返回5行記錄,花費342.74 ms.
        

參數說明:

  • innodb_buffer_pool

    該部分緩衝是InnoDB引擎最重要的快取區域,通過高效利用記憶體資源,極大地加速了資料的讀取與修改操作,從而顯著提高了資料庫的整體效能。其中主要包含資料頁、索引頁、undo頁、insert buffer、自適應雜湊索引、鎖資訊以及資料字典等資訊。在進行SQL讀和寫的操作時,首先並不是對物理資料檔案操作,而是先對buffer_pool進行操作,然後再通過checkpoint等機制寫回資料檔案。該空間的優點是可以提升資料庫的效能、加快SQL運行速度,缺點是故障恢複速度較慢。

  • innodb_log_buffer

    該部分主要存放redo log的資訊,在RDS MySQL執行個體中會設定1 MB的大小,InnoDB會首先將redo log寫在這裡,然後按照一定頻率將其重新整理回重做記錄檔中。該空間不需要太大,因為一般情況下該部分緩衝會以較快頻率重新整理至redo log(Master Thread會每秒重新整理、事務提交時會重新整理、其空間少於1/2時同樣會重新整理)。

  • innodb_additional_mem_pool

    該部分主要存放InnoDB內的一些資料結構,在RDS MySQL執行個體中統一設定為2 MB。通常是在buffer_pool申請記憶體事,還需要在額外記憶體中申請空間儲存該對象的結構資訊。該大小主要與表數量有關,表數量越大需要更大的空間。

  • key_buffer

    該部分是MyISAM表的重要快取區域,所有執行個體統一為16 MB。該部分主要存放MyISAM表的鍵。MyISAM表不同於InnoDB表,其緩衝的索引緩衝是放在key_buffer中的,而資料緩衝則儲存於作業系統的記憶體中。 RDS MySQL執行個體的系統是MyISAM引擎的,因此在RDS MySQL執行個體中是給予該部分一定量的空間。

  • query_cache

    該部分是對查詢結果做緩衝以減少解析SQL和執行SQL的開銷,在RDS MySQL執行個體中關閉了該部分的緩衝。主要適合於讀多寫少的應用情境,因為它是按照SQL語句的hash值進行緩衝的,當表資料發生變化後即失效。

Session私人記憶體

共用記憶體中介紹的記憶體空間是執行個體建立時即分配的記憶體空間,並且是所有串連共用的,而出現OOM異常的執行個體都是由於下面各個串連私人的記憶體造成的。

執行如下命令,查詢樣本的Session私人記憶體配置情況:

show variables where variable_name in (
'read_buffer_size','read_rnd_buffer_size','sort_buffer_size','join_buffer_size','binlog_cache_size','tmp_table_size'
);
            

查詢結果如下(如下為測試執行個體配置):

+-------------------------+-----------------+
| Variable_name           | Value           |
+-------------------------+-----------------+
| binlog_cache_size       | 262144          |
| join_buffer_size        | 262144          |
| read_buffer_size        | 262144          |
| read_rnd_buffer_size    | 262144          |
| sort_buffer_size        | 262144          |
| tmp_table_size          | 262144          |
+-------------------------+-----------------+
共返回 6 行記錄,花費 356.54 ms.
            

參數說明:

  • read_buffer&read_rnd_buffer

    分別存放了對順序和隨機掃描(例如按照排序的順序訪問)的緩衝,RDS MySQL執行個體給每個Session設定256 KB的大小。當thread進行順序或隨機掃描資料時會首先掃描該buffer空間以避免更多的物理讀。

  • sort_buffer

    需要執行order by和group by的SQL都會分配sort_buffer,用於儲存排序的中間結果,在RDS MySQL執行個體中設定256 KB。在排序過程中,若儲存量大於sort_buffer_size,則會在磁碟產生暫存資料表以完成操作。在Linux 系統中,當分配空間大於2 MB時會使用mmap()而不是malloc()來進行記憶體配置,導致效率降低。

  • join_buffer

    RDS MySQL僅支援nested loop的join演算法,RDS MySQL執行個體設定256 KB的大小,處理邏輯是驅動表的一行和非驅動表聯合尋找,這時就可以將非驅動表放入join_buffer,不需要訪問擁有並發保護機制的buffer_pool。

  • binlog_cache

    該地區用來緩衝該thread的binlog日誌,RDS MySQL執行個體設定256 KB的大小。在一個事務還沒有commit之前會先將其日誌儲存於binlog_cache中,等到事務commit後會將其binlog刷回磁碟上的binlog檔案以持久化。

  • tmp_table

    不同於上面各個Session層次的buffer,這個參數可以在控制台上修改。該參數是指使用者記憶體暫存資料表的大小,如果該thread建立的暫存資料表超過它設定的大小會把暫存資料表轉換為磁碟上的一張MyISAM暫存資料表。如果使用者在執行事務時遇到類似如下這樣的錯誤,可以考慮增大tmp_table的值。

    [Err] 1114 - The table '/home/mysql/data3081/tmp/#sql_6197_2' is full