Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

10.12.3.1 MySQL如何使用内存

MySQL分配缓冲区和缓存以提高数据库操作的性能。默认配置旨在允许MySQL服务器在具有大约512MB RAM的虚拟机上启动。你可以通过增加某些缓存和缓冲区相关的系统变量的值来提高MySQL性能。你也可以修改默认配置以在内存有限的系统上运行MySQL。

以下列表描述了MySQL使用内存的一些方式。在适用情况下,相关的系统变量将被引用。一些项目是存储引擎或功能特定的。

  • InnoDB缓冲池是一个内存区域,用于缓存InnoDB表、索引和其他辅助缓冲区。为了高效地执行大量读取操作,缓冲池被分成可以容纳多行的。为了高效地管理缓存,缓冲池被实现为一个链表的页;很少使用的数据将被从缓存中删除,使用一种LRU算法的变体。更多信息,请参见第17.5.1节,“缓冲池”

    缓冲池的大小对系统性能非常重要:

  • 存储引擎接口使优化器能够提供关于记录缓冲区大小的信息,以便扫描估计将读取多行的记录。缓冲区大小可以根据估计的大小而变化。InnoDB使用这种可变大小的缓冲区功能来利用行预取,并减少锁定和B树导航的开销。

  • 所有线程共享MyISAM键缓冲区。key_buffer_size系统变量确定其大小。

    对于每个MyISAM表,服务器打开一次索引文件;对于每个并发线程访问表,数据文件打开一次。对于每个并发线程,表结构、每列的列结构和大小为3 * N的缓冲区被分配(其中N是最大行长度,不包括BLOB列)。一个BLOB列需要五到八个字节加上BLOB数据的长度。MyISAM存储引擎维护一个额外的行缓冲区用于内部使用。

  • 可以将myisam_use_mmap系统变量设置为1,以启用所有MyISAM表的内存映射。

  • 如果内部内存临时表变得太大(根据tmp_table_sizemax_heap_table_size系统变量确定),MySQL会自动将表从内存格式转换为磁盘格式,该格式使用InnoDB存储引擎。你可以按照第10.4.4节“MySQL中的内部临时表使用”中所述增加允许的临时表大小。

    对于使用MEMORY存储引擎显式创建的表,只有max_heap_table_size系统变量确定表可以增长的大小,并且不会转换为磁盘格式。

  • MySQL性能架构是一个监控MySQL服务器执行的低级功能。性能架构动态分配内存,以实际服务器负载为基础,而不是在服务器启动时分配所需的内存。一旦分配了内存,直到服务器重新启动前都不会释放。有关更多信息,请参阅第29.17节“性能架构内存分配模型”

  • 服务器用于管理客户端连接的每个线程都需要一些线程特定的空间。以下列表指出了这些空间和控制其大小的系统变量:

    连接缓冲区和结果缓冲区每个都以net_buffer_length字节为大小,但可以根据需要动态扩展到max_allowed_packet字节。结果缓冲区在每个SQL语句后都会缩小到net_buffer_length字节。同时,当前语句字符串的副本也会被分配。

    每个连接线程都使用内存来计算语句摘要。服务器为每个会话分配max_digest_length字节。请参阅第29.10节“性能架构语句摘要和采样”

  • 所有线程共享相同的基本内存。

  • 当线程不再需要时,分配给它的内存将被释放并返回系统,除非线程返回线程缓存。在那种情况下,内存将保持分配。

  • 每个请求都执行顺序扫描表时,会分配一个读取缓冲区。系统变量read_buffer_size确定缓冲区大小。

  • 当读取行以任意顺序(例如,按照排序)时,可能会分配一个随机读取缓冲区以避免磁盘寻道。系统变量read_rnd_buffer_size确定缓冲区大小。

  • 所有连接都在单个传递中执行,并且大多数连接都不需要使用临时表。大多数临时表都是基于内存的哈希表。具有大行长度(计算为所有列长度之和)或包含BLOB列的临时表将存储在磁盘上。

  • 大多数执行排序的请求都分配一个排序缓冲区和零到两个临时文件,具体取决于结果集大小。请参阅B.3.3.5节“MySQL存储临时文件的位置”

  • 几乎所有的解析和计算都在线程本地和可重用的内存池中进行。对于小项目,不需要内存开销,从而避免了正常的慢速内存分配和释放。只有在出现意外的大字符串时才需要分配内存。

  • 对于每个具有 BLOB 列的表,一个缓冲区将动态扩展以读取更大的 BLOB 值。如果您扫描表,则缓冲区将增长到最大的 BLOB 值。

  • MySQL 需要表缓存的内存和描述符。所有在用表的处理器结构都保存在表缓存中,并以 先进先出 (FIFO) 方式管理。 table_open_cache 系统变量定义了初始表缓存大小;见 第 10.4.3.1 节,“MySQL 如何打开和关闭表”

    MySQL 还需要表定义缓存的内存。table_definition_cache 系统变量定义了可以存储在表定义缓存中的表定义数量。如果您使用大量表,可以创建一个大型表定义缓存以加速表的打开。表定义缓存占用较少的空间,不使用文件描述符,与表缓存不同。

  • 一个 FLUSH TABLES 语句或 mysqladmin flush-tables 命令关闭所有未使用的表,并标记所有在用表以便在当前执行线程完成时关闭。这将释放大多数在用内存。FLUSH TABLES 不会返回,直到所有表都关闭。

  • 服务器在内存中缓存信息,以便 GRANTCREATE USERCREATE SERVERINSTALL PLUGIN 语句。这部分内存不会被相应的 REVOKEDROP USERDROP SERVERUNINSTALL PLUGIN 语句释放,除非使用 FLUSH PRIVILEGES 释放。

  • 在复制拓扑结构中,以下设置影响内存使用,可以根据需要进行调整:

    • 在复制源上,max_allowed_packet 系统变量限制了源发送给副本的最大消息大小,默认为 64M。

    • 在多线程副本上,replica_pending_jobs_size_max 系统变量设置了用于持有待处理消息的最大内存量,默认为 128M。内存只有在需要时分配,但可能会在处理大事务时使用。这是一个软限制,大事务可以被处理。

    • 在复制源或副本上,rpl_read_size 系统变量控制从二进制日志文件和中继日志文件读取的最小数据量,默认为 8192 字节。每个线程读取二进制日志和中继日志文件时,包括源上的转储线程和副本上的协调器线程,会分配一个该值大小的缓冲区。

    • 在复制源上,binlog_transaction_dependency_history_size 系统变量限制了作为内存历史记录的行哈希数。

    • 在复制源上,max_binlog_cache_size 系统变量指定了单个事务的内存使用上限。

    • 在复制源上,max_binlog_stmt_cache_size 系统变量指定了语句缓存的内存使用上限。

ps 和其他系统状态程序可能报告说 mysqld 使用了大量内存。这可能是由于不同内存地址上的线程栈所致。例如,Solaris 版本的 ps 将栈之间未使用的内存计为已使用的内存。要验证这一点,可以使用 swap -s 检查可用的交换空间。我们使用多个内存泄露检测器(包括商业和开源的)测试 mysqld,因此不应该有内存泄露。