Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


10.12.3.1 MySQL 如何使用内存

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

以下列表描述了 MySQL 如何使用内存。在可应用的地方,相关系统变量将被引用。一些项目是存储引擎或特性专门的。

  • InnoDB 缓冲池是一个内存区域,用于存储 InnoDB 表、索引和其他辅助缓存的数据。为了提高高容量读操作的效率,该缓冲池被分割成页面,每个页面可以包含多行数据。为了提高缓存管理的效率,该缓冲池实现为一个链表结构的页面;Rarely 使用的数据将被从缓存中淘汰,使用 LRU 算法的变体。更多信息请见第17.5.1节,“Buffer Pool”

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

  • 存储引擎接口使得优化器能够提供关于扫描时要使用的记录缓冲区大小的信息。该缓冲区大小可以根据估算值进行调整。InnoDB 使用这个可变大小缓冲区能力来实现行预取和减少 latch 和 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内部临时表的使用”中描述的方法增加临时表的最大大小。

    对于使用CREATE TABLE创建的MEMORY表,只有max_heap_table_size系统变量确定了表可以增长到多大,且不会转换为磁盘格式。

  • MySQL性能_schema是用于监控MySQL服务器执行的低级别特性。性能_schema动态地分配内存,根据实际服务器负载来调整内存使用,而不是在服务器启动时分配所需的内存。一旦内存被分配,它将不会释放直到服务器重新启动。更多信息,请见第29.17节,“性能_schema内存分配模型”

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

    连接缓冲区和结果缓冲区每个开始大小都等于net_buffer_length字节,但是在需要时可以动态地扩展到max_allowed_packet字节。结果缓冲区在每个SQL语句执行后将会缩小到net_buffer_length字节。在语句正在运行时,也会分配当前语句字符串的副本。

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

  • 所有线程共享同一个基础内存。

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

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

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

  • 所有连接都在单个循环中执行,且大多数连接可以不使用临时表完成。最常见的临时表是内存基表。包含大量行长(计算为所有列长度之和)或包含BLOB列的临时表将被存储在磁盘上。

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

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

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

  • MySQL 需要内存和描述符来缓存表。Handler 结构对于所有在用表都保存在表缓存中,并以First In, First Out(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语句释放,因此对于执行了许多导致缓存的语句的服务器,cached 内存使用将增加,除非使用FLUSH PRIVILEGES来释放。

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

    • 在复制源服务器上,max_allowed_packet系统变量限制了源服务器将消息发送给其副本的最大大小。这一设置默认为64M。

    • 系统变量replica_pending_jobs_size_max在多线程副本中设置了等待处理的消息所占用的最大内存量。该设置默认为128M。当需要时才分配内存,但如果您的复制拓扑偶尔处理大事务,这可能会被使用。这是一个软限制,允许处理更大的事务。

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

    • 系统变量binlog_transaction_dependency_history_size限制了内存中保留的行哈希数量。

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

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

ps 和其他系统状态程序可能报告 mysqld 使用了大量内存。这可能是由于线程栈在不同内存地址上引起的。例如,Solaris 版本的 ps 将栈之间的未使用内存计入使用内存。要验证此问题,请使用 swap -s 命令检查可用交换空间。我们使用多种内存泄露检测器(包括商业和开源版本),因此应该没有内存泄露。