MySQL如何使用内存

本文问题

  1. MySQL内存使用可以分为哪几大类?
  2. 在MySQL中,哪些内存是自动释放的,哪些内存是可以手动释放的,哪些内存是只能重启释放的?
  3. 对于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_sizemax_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 SERVERUNINSTALL PLUGIN语句释放。
所以执行许多这类语句会导致缓存使用增加,这部分内存可以使用FLUSH PRIVILEGES语句释放。

问题答案

  1. MySQL内存使用可以分为哪几大类?
  • 存储引擎使用的,包括InnoDB缓冲池innodb_buffer_pool_size和MyISAM索引缓冲区key_buffer_size
  • 表缓存相关的,包括table_open_cachetable_definition_cache
  • 内存临时表,内部临时表超过max_heap_table_sizetmp_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使用的内存。根据配置和需要进行增长。
  1. 在MySQL中,哪些内存是自动释放的,哪些内存是可以手动释放的,哪些内存是只能重启释放的?
  • 自动释放
    线程分配的内存在线程结束后自动释放
    请求占用的内存在请求结束后也会自动释放
  • 手动释放
    InnoDB缓冲池占用的内存可以通过在线更改innodb_buffer_pool_size释放
    MyISAM索引缓存可以通过在线更改key_buffer_size进行释放
    表缓存可以通过FLUSH TABLES进行释放
    权限表缓存可以通过FLUSH PRIVILEGES进行释放
  • 重启释放
    Performance_schema使用的内存只能重启释放
  1. 对于InnoDB和MyISAM存储引擎,MySQL分配内存有什么区别?
    InnoDB使用InnoDB缓冲池,其中包括数据和索引,由innodb_buffer_pool_size定义其大小
    MyISAM使用MyISAM索引缓存,其中只包括索引,由key_buffer_size定义其大小

你可能感兴趣的:(MySQL如何使用内存)