本文问题
- MySQL内存使用可以分为哪几大类?
- 在MySQL中,哪些内存是自动释放的,哪些内存是可以手动释放的,哪些内存是只能重启释放的?
- 对于InnoDB和MyISAM存储引擎,MySQL分配内存有什么区别?
内存使用情况
存储引擎
InnoDB
InnoDB缓冲池,大小通过innodb_buffer_pool_size
定义,里面包含了InnoDB的表的数据、索引和一些额外信息。
数据库启动时通过malloc()
函数分配整个缓冲池大小的内存。可以在数据库运行时,通过修改innodb_buffer_pool_size
大小来手动释放部分内存。
MyISAM
MyISAM索引缓存,这部分内存由所有线程共享。大小通过key_buffer_size
定义。
对于MyISAM表的打开,索引文件只打开一次,每个对表的并行访问都会打开一次数据文件。对于每个并发线程,缓存表结构,每个列的列结构,并且会缓存一个大小为3*N
的缓冲区(N
是除了BLOB
以外其他列的最大行大小)。BLOB列需要BLOB数据再加上额外的5-8 bytes
。MyISAM存储引擎维持一个额外的行缓冲区用于内部使用
myisam_use_mmap
是否使用内存映射来读写MyISAM表。
临时表
内部临时表
内部临时表的大小由tmp_table_size
和max_heap_table_size
中较小值决定其最大大小。超过两者中的最小值后会由内存表转换为磁盘表。
用户创建的临时表
通过CREATE TABLE
语句创建的内存表,max_heap_table_size
定义了表的最大大小,并且这类表不会转换为临时表
Performance_schema
Performance_schema在需要时动态增加内存。这部分内存一旦分配,只能通过重启数据库进行释放
线程
所有线程共享相同的基本内存
每个线程还需要一些特定与线程的内存,当线程结束时,分配给线程的内存会释放回操作系统。如果线程结束后进入到线程缓冲池,分配给线程的内存不会释放。
- 堆栈
thread_stack
- 连接缓冲区
net_buffer_length
- 结果缓冲区
net_buffer_length
连接缓冲区和结果缓冲区都是从net_buffer_length
大小开始分配,可以根据需要动态扩展到max_allowed_packed
大小。每个SQL语句结束后,结果缓冲区会缩小到net_buffer_length
大小。在运行语句时,还会分配正在执行的语句字符串大小的内存。
每个连接线程都要使用内存来计算语句含义,服务器为每个会话分配max_digest_length
大小的内存
请求
顺序读请求会分配一个读缓冲区 read_buffer_size
随机读请求也会分配一个随机读缓冲区 read_rnd_buffer_size
联接join
语句一次执行,大多数join
可以在不使用临时表的情况下完成,大部分临时表时内存表。
大部分排序请求根据结果集的大小,分配一个排序缓冲区和0到2个临时文件。
基本上所有的解析和计算都在线程本身的可重用的内存池中完成。对于小的项目,不需要内存开销,这可以避免大量小内存分配和释放。只有意外出现大字符串的时候才需要分配内存。
对于每个BLOB
列,将动态扩展缓冲区以读取BLOB
值。在扫描表的时候,缓冲区将增大到BLOB
列的最大值。
表缓存
MySQL需要为表缓存提供内存和文件描述符。所有使用中的表结构都存储在表缓存中,并按照先进先出原则进行管理。table_open_cache
定义了初始表缓存的大小
MySQL也需要为表定义缓存提供内存。table_definition_cache
定义了可以在表定义缓存中缓存的表定义文件(.frm文件
)数量。
FLUSH TABLES
语句或者mysqladmi flush-tables
命令立即关闭所有未使用的表,并在线程执行结束时将所有正在使用中的表标记为关闭。这样可以释放大多数使用中的内存。FLUSH TABLES
在关闭所有表之前不会返回
权限
数据库在内存中缓存 GRANT
,CREATE USER
,CREATE SERVER
以及INSTALL PLUGIN
语句的结果。
这些内存不会通过REVOKE
,DROP USER
,DROP SERVER
和UNINSTALL PLUGIN
语句释放。
所以执行许多这类语句会导致缓存使用增加,这部分内存可以使用FLUSH PRIVILEGES
语句释放。
问题答案
- MySQL内存使用可以分为哪几大类?
- 存储引擎使用的,包括InnoDB缓冲池
innodb_buffer_pool_size
和MyISAM索引缓冲区key_buffer_size
。 - 表缓存相关的,包括
table_open_cache
和table_definition_cache
- 内存临时表,内部临时表超过
max_heap_table_size
和tmp_table_size
中的较小值后会转换为磁盘表。使用CREATE TABLE
语句创建的临时表不进行转换,但是大小不能超过max_heap_table_size
- 线程的内存,在线程结束(并且线程不回到
thread cache
)后释放。
每个客户端连接线程都需要堆栈thread_stack
,连接缓冲区,结果缓冲区。连接缓冲区和结果缓冲区都是以net_buffer_length
大小开始的,可以根据需要扩展到max_allowed_packet
大小。在SQL语句结束后,结果缓冲区会缩小回net_buffer_length
大小 - 权限表缓存。数据库缓存以下语句的结果:
CREATE USER
,GRANT
,CREATE SERVER
,INSTALL PLUGIN
- Performance_schema使用的内存。根据配置和需要进行增长。
- 在MySQL中,哪些内存是自动释放的,哪些内存是可以手动释放的,哪些内存是只能重启释放的?
- 自动释放
线程分配的内存在线程结束后自动释放
请求占用的内存在请求结束后也会自动释放 - 手动释放
InnoDB缓冲池占用的内存可以通过在线更改innodb_buffer_pool_size
释放
MyISAM索引缓存可以通过在线更改key_buffer_size
进行释放
表缓存可以通过FLUSH TABLES
进行释放
权限表缓存可以通过FLUSH PRIVILEGES
进行释放 - 重启释放
Performance_schema使用的内存只能重启释放
- 对于InnoDB和MyISAM存储引擎,MySQL分配内存有什么区别?
InnoDB使用InnoDB缓冲池,其中包括数据和索引,由innodb_buffer_pool_size
定义其大小
MyISAM使用MyISAM索引缓存,其中只包括索引,由key_buffer_size
定义其大小
网友评论