【译】MySQL如何打开和关闭表

前言

这是一篇dev.mysql.com中的文章,主要讲了MySQL的表缓冲机制,对table_open_cache进行了详细的讲解。
在【】内的内容为译者注,旨在使文章更容易理解和表达译者的观点。
译者英语水平和专业知识水平有限,翻译时仍未通透的理解这一机制。希望我们可以进行深入的讨论来提供此文的正确性和易读性。
原文:https://dev.mysql.com/doc/refman/5.6/en/table-cache.html
译者:imdyc.com

MySQL如何打开和关闭表

MySQL是多线程的,所以可能会有很多客户同时向一个表发送查询。为了简化“多个客户机并发访问同一个表”这一问题,表由每个并发会话独立打开。这通常使用额外的内存,但增加了并发性。MyISAM引擎的每个客户端打开的表都额外需要一个数据文件的文件描述符。(相比之下,索引文件描述符在所有会话之间共享)。

table_open_cache和 max_connections系统变量影响服务器保持打开的最大文件数。如果你增加他们其中一个(或同时增加两个)的值,你可能遇到MySQL无法打开更多文件的错误。许多操作系统允许你增加打开的文件限制,因系统而异。参考操作系统文档以确定是否可以增加限制以及如何这样如何增加限制。
【在我的Linux中将该值增加到20,000时,mysql无法重启成功,可能是在载入该配置时被Linux拒绝,linux用户可以在/etc/security/limits.conf配置mysql用户的文件数限制,最大为65535

@root soft nofile 65535
@root hard nofile 65535

重启操作系统后生效。

table_open_cache 和 max_connections相关, 举个例子: 有200个并发的连接时,最少需要指定表高速缓存区大小为 200*N,其中N为查询能涉及到的最大数量的表,而且你还必须准备额外的临时描述符,来服务于临时表。
如果table_open_cache值设置过高,MySQL可能会耗尽文件描述符并且断开连接,这会使MySQL可靠性下降。在服务器启动时,这个高速缓存区的大小会被自动设置。值得注意的是,MySQL可能会临时打开比这个值更多的表来查询。

MyISAM存储引擎打开每一个表都需要两个文件描述符。在MyISAM分区表中,每个分区的open table操作都需要两个文件描述符。(更需要注意的是:MyISAM打开一个分区表时,将会打开表中的每个分区,关于分区是否实际使用。请查看MyISAM and partition file descriptor usage。)
你可以使用”open-files-limit” 为MySQL增加可用的文件描述符的数量。在Section B.5.2.18, “File Not Found and Similar Errors”这个错误的解决办法中有详细介绍。
在缓存中打开的表数量保持在table_open_cache限制之内。服务器在启动时自动调整缓存大小。要显式设置大小,请在启动时设置table_open_cache变量。请注意:【因为临时表的存在】MySQL可能暂时打开比此更多的表执行查询。

MySQL在以下情况下关闭未使用的表并将其从表缓存中删除:

  • 当缓存已满时,线程尝试打开不在缓存中的表。

  • 当缓存中包含其他的“table_open_cache”,并且高速缓存中 的表不再被任何线程使用时。【我的理解是,一个服务器中可以创建多个表缓存区,当其中的一个(或一部分)缓冲区不再被使用时就会删除掉缓冲区以及整个缓冲区里的表缓存】

  • 当清洗表(flush table)操作发生时。比如当有人发出FLUSH TABLES语句,或执行 mysqladmin flush-tables,或 mysqladmin refresh命令时。

当表缓存填满时,服务器使用以下过程来“安置”要使用的缓存条目:

  • 以近期利用率为顺序,释放当前不在使用的表。

  • 如果需要打开新表,但缓存已满,并且不能释放表,则缓存将根据需要临时扩展。当缓存处于临时扩展状态并且表从使用状态变为未使用状态时,表被关闭并从高速缓存释放。

 

MyISAM【其实大多数存储引擎都这样】为每个并发访问打开一个表。也就是说:如果两个线程访问同一个表,或者一个线程在同一个查询中访问该表两次(例如将表连接到其自身),表都会打开两次【Opened_tables记录+2】。
任何MyISAM表的第一次打开都需要两个文件描述符:一个用于数据文件,一个用于索引文件。每次额外调用该表时,只需要一个数据文件的文件描述符。索引文件的文件描述符在所有线程之间共享。

如果使用HANDLER tbl_name语句打开表,则为该线程分配一个专用表对象。该表对象不被其他线程共享,并且在线程调用HANDLER tbl_name CLOSE或线程终止之前不会关闭。当这种情况发生时,表被放回表缓存中(如果缓存未满)。更多请参见 Section 13.2.4, “HANDLER Syntax”

您可以通过检查mysqld状态变量:Opened_tables 来确定表缓存是否太小:

mysql> SHOW GLOBAL STATUS LIKE 'Opened_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Opened_tables | 2741 |
+---------------+-------+

如果值非常大或者增加速度很快,就说明表的缓存过小了。
增加表缓存的大小参见 Section 5.1.5, “Server System Variables”Section 5.1.7, “Server Status Variables”

为了避免造成不必要的误会,转载请保留出处:https://imdyc.com/database/mysql如何在打开和关闭表.html ‎

您可能还喜欢...

发表评论

电子邮件地址不会被公开。 必填项已用*标注