经常在项目上碰到在没有大并发活跃 SQL 的情况下,MySQL 所占用的物理内存远大于 InnoDB_Buffer_Pool 的配置大小。我起初是怀疑被 performance_schema 吃掉了或是 MySQL 存在内存泄露,而后发现并非如此。是自己对于 MySQL 和 Linux 的内存管理不了解所致,因此本篇就来深入讨论下,有何不对或者不严谨的地方欢迎提出~
先简单说下个人对于 MySQL 内存分配的基础认识,可能会存在部分认知偏差:
MySQL 的内存占用主要由两部分组成,global_buffers 与 all_thread_buffers,其中 global_buffers 为全局共享缓存,all_thread_buffers 为所有线程独立缓存,如下图所示:
Server version: 5.7.27-log MySQL Community Server (GPL)
接着我们再来看下 MySQL 内部是管理内存的,查阅大量资料后,发现我原先的理解不是很正确,之前我习惯性的把 MySQL 的内存划分为 Innodb_buffer_pool、Sharing 、Thread memory 等三大类,但实际应该以 MySQL 的架构来划分内存管理比较合理。即 Server 层与 InnoDB 层(Engine 层),而这两块内存是由不同的方式进行管理的。
其中 Server 层是由 mem_root 来进行内存管理,包括 Sharing 与 Thead memory;而 InnoDB 层则主要由 Free List、LRU List、FLU List 等多个链表来统一管理 Innodb_buffer_pool。