關於mysql占用內存不釋放的實驗結論


一、現象

  可能大家都遇到過這么一種現象。MySQL占用着內存不釋放,然后還時不時的一點點增加。

二、問題排查

  結合官方文檔 https://dev.mysql.com/doc/refman/5.7/en/memory-use.html 和 percona文檔 https://www.percona.com/blog/2018/06/28/what-to-do-when-mysql-runs-out-of-memory-troubleshooting-guide/

       得出以下MySQL占用內存的計算方法

--查看每個線程占用多少內存,然后乘以正在運行的線程(也就是排查sleep的)。
SELECT ( ( @@read_buffer_size
+ @@read_rnd_buffer_size
+ @@sort_buffer_size
+ @@join_buffer_size
+ @@binlog_cache_size
+ @@thread_stack
+ @@max_allowed_packet
+ @@net_buffer_length )
) / (1024*1024) AS MEMORY_MB;

--查看MySQL全局占用多少內存
select (@@innodb_buffer_pool_size
+@@innodb_log_buffer_size
+@@key_buffer_size) / 1024 /1024 AS MEMORY_MB;

--查看performance_schema占用多少內存
SELECT SUBSTRING_INDEX(event_name,'/',2) AS
       code_area, sys.format_bytes(SUM(current_alloc))
       AS current_alloc
       FROM sys.x$memory_global_by_current_bytes
       GROUP BY SUBSTRING_INDEX(event_name,'/',2)
       ORDER BY SUM(current_alloc) DESC;

--查看 memory 存儲引擎占用多少內存
select sum(max_data_length)/1024/1024 as MEMORY_MB from tables where engine='memory';

  再把上面的結果相加,就是MySQL當前占用的內存大小。但問題是算出來的結果比實際的小了很多。但如果拿歷史最大連接數去算的話,結果是差不多的。所以,就在懷疑,MySQL是否有一個內存的“高水位“。因此帶着疑問做了以下實驗

 

三、實驗

操作系統:centos 7.4

MySQL:percona 5.7.23

內存:32G

innodb_buffer_pool_size:8G

 

3.1 首先重啟MySQL,釋放掉內存,重啟后,innodb_buffer_pool 中有 free_page,這時候,使用 sysbench 生成 8G 數據。全表掃描 sbtest1,把innodb_buffer_pool 占滿,觀察當前MySQL占用的內存

--全表掃描sbtest1
select count(*) from (select * from sbtest1) a;

--查看innodb_buffer_pool情況
select sum(POOL_SIZE),sum(free_buffers),sum(DATABASE_PAGES) from INNODB_BUFFER_POOL_STATS;
+----------------+-------------------+---------------------+
| sum(POOL_SIZE) | sum(free_buffers) | sum(DATABASE_PAGES) |
+----------------+-------------------+---------------------+
|         524224 |              6537 |              517687 |
+----------------+-------------------+---------------------+

因為我設置 innodb_buffer_pool_instance = 8,innodb_lru_scan_depth = 1024。所以 free_page 最大會剩余 8192 個 buffer。

top 觀察到當前 MySQL 占用 8.8G左右

 

3.2 調整線程。thread 增加到50個,然后觀察內存。

 

 

0.010 * 1024 = 10.24G 左右。內存從 8.8G 增加到 10.24G,等到查詢結束,MySQL內存並沒有釋放回 8.8G

 

3.3 把 thread 調整到 10個,觀察內存

 

內存並沒有增加

 

3.4 把 thread 調整到 100個,觀察內存

 

0.012 * 1024 = 12.28(G) 左右

 

四、結論

從目前的實驗結果來看,mysql 會把內存占用不釋放,像是有一個歷史高水位在那里,比如說,我歷史跑過最大連接數 50 個,mysqld占用了 10.24G內存,接下來跑 10個連接數的時候,則內存不會增加。最后跑了100個連接數,內存又增加到12.28G。然后就一直保持在12.28G。

該結論純屬由實驗得出的,可能有錯誤,偏差的地方。如果有朋友覺得結論有錯誤,或者覺得以偏概全,可以聯系 QQ:505701092。歡迎一起討論或者指正,謝謝!

       

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM