美文网首页MySql
第46问:MySQL 使用的文件句柄突增, 该如何诊断

第46问:MySQL 使用的文件句柄突增, 该如何诊断

作者: 爱可生开源社区 | 来源:发表于2021-10-14 13:35 被阅读0次
    image

    在 第44问 中, 我们使用 tcmalloc 提供的工具, 来查看 MySQL 的内存分配

    该方法对性能影响不大, 可以在生产环境运行, 但需要将 MySQL 的分配器配置成 tcmalloc

    在本次实验中, 我们介绍另外一种方法, 针对于 MySQL 的内存突增情况进行诊断

    实验

    我们依然宽油起一个数据库:

    image

    本实验中, 我们需要模拟MySQL的内存突增的情况. 我们从 MySQL 的 bug 库里找到一个易于复现的相关 bug: https://bugs.mysql.com/bug.php?id=99382

    这个 bug 的描述很清晰, 并提供了一个 SQL 脚本, 直接执行该脚本就可以复现内存激增的情况:

    image

    我们来试一下:

    image

    当前 MySQL 的内存占用为181M

    执行脚本:

    image

    在脚本执行过程中, 我们会发现 MySQL 使用的内存在不断上涨

    image

    现在我们来诊断 MySQL 对内存的使用. 在脚本执行过程中, 同时执行如下命令进行观测:

    image

    小贴士

    什么是系统调用mmap?

    简单来说, MySQL不是直接向Linux申请内存, 而是向glibc申请内存. glibc会维持一个内存池, 当glibc发现内存池吃紧时, 会通过系统调用mmap(或者brk)向Linux申请内存.

    所以我们监听系统调用mmap, 也就监听了MySQL在什么情况下需要大量内存 (即什么时候glibc的内存池吃紧了)


    至于glibc内存分配的机制, 可参考阅读: https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/

    可以看到在当前目录下生成了 perf.data :

    image

    我们将 perf.data 转换成可读的方式:

    image

    简单看一下 perf.out , 我们会看到每次 mmap 的调用都记录了足够的信息, 包括:

    1. 图中红色标记的部分, 是要求分配内存的线程号. 有了线程号, 我们就可以找到是哪个SQL在占用内存.
    2. 图中蓝色标记的部分, 是分配内存的大小
    3. 图中绿色标记的部分, 是分配内存时的堆栈信息

    有了线程号和堆栈信息, 我们就可以判断是哪个 SQL(或者 MySQL 的哪个内部线程), 在什么情况下要求分配内存

    本例中, 我们判断29735号进程, 在 create view 这个操作中, 打开表时需要分配内存

    当然, perf.out 文件很长, 大家需要将信息都聚合在一起, 再判断谁是最消耗内存的

    局限

    本实验所介绍的方法是有局限的: 本方法适用于 MySQL 内存激增的情况, 在其他情况下 (比如内存缓慢并持续增长), 本方法不一定能观测到准确的信息.

    如小贴士所述,MySQL 向 glibc 申请内存 (第一步), glibc 的内存池吃紧时,glibc 再向 Linux 申请内存 (第二步).

    在内存激增的情况下, 第一步的发生 大概率会导致 第二步的发生, 我们观测系统调用 mmap , 实际上是观察到了第二步的发生, 推导出第一步的原因.

    而在内存缓慢增长的情况下, 第一步的发生 小概率会导致 第二步的发生, 导致无法从第二步推导第一步.

    比如: 由于某个原因, 内存缓慢增长, 当 glibc 的内存池即将吃紧时, 发生了其他业务 SQL , 导致这些业务 SQL 触发了 glibc 内存池吃紧, 那么我们诊断出内存增长的原因是因为业务 SQL , 而真正的原因被藏了起来.

    使用本方法时, 希望大家能注意到这个局限.


    关于 MySQL 的技术内容,你们还有什么想知道的吗?赶紧留言告诉小编吧!

    相关文章

      网友评论

        本文标题:第46问:MySQL 使用的文件句柄突增, 该如何诊断

        本文链接:https://www.haomeiwen.com/subject/yytuoltx.html