zoukankan      html  css  js  c++  java
  • 关于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。欢迎一起讨论或者指正,谢谢!

           

  • 相关阅读:
    LightOj1054
    LightOj1028
    Docker仓库(转载)
    Dockerfile(转载)
    Docker存储卷(转载)
    容器虚拟化网络和Docker容器网络(转载)
    Docker镜像管理基础(转载)
    Docker基础用法(转载)
    docker容器技术基础入门(转载)
    Redis 3种安装部署方式
  • 原文地址:https://www.cnblogs.com/ziroro/p/9779663.html
Copyright © 2011-2022 走看看