当您执行 mysqladmin status 命令时,您应该看到类似以下内容
Uptime: 426 Running threads: 1 Questions: 11082
Reloads: 1 Open tables: 12
如果您拥有少于 12 个表,则 Open tables
值为 12 可能有些令人费解。
MySQL 是多线程的,因此可能会有许多客户端同时对给定表发出查询。为了最大程度地减少多个客户端会话对同一个表具有不同状态的问题,每个并发会话都会独立地打开该表。这会使用额外的内存,但通常会提高性能。对于 MyISAM
表,每个打开表的客户端都需要一个额外的文件描述符用于数据文件。(相比之下,索引文件描述符在所有会话之间共享。)
table_open_cache
和 max_connections
系统变量会影响服务器保持打开状态的文件的最大数量。如果您增加一个或两个变量的值,您可能会遇到操作系统对每个进程的打开文件描述符数量施加的限制。许多操作系统允许您增加打开文件限制,尽管方法在各个系统之间差异很大。请查阅您的操作系统文档以确定是否可以增加限制以及如何增加限制。
table_open_cache
与 max_connections
相关。例如,对于 200 个并发运行的连接,请指定至少 200 *
的表缓存大小,其中 N
N
是您执行的任何查询中每个连接的最大表数。您还必须为临时表和文件保留一些额外的文件描述符。
请确保您的操作系统能够处理 table_open_cache
设置所暗示的打开文件描述符数量。如果 table_open_cache
设置过高,MySQL 可能会耗尽文件描述符,并出现拒绝连接或无法执行查询等症状。
还要考虑到 MyISAM
存储引擎需要为每个唯一的打开表提供两个文件描述符。要增加 MySQL 可用的文件描述符数量,请设置 open_files_limit
系统变量。参见 第 B.3.2.16 节,“找不到文件以及类似错误”。
打开表的缓存保持在 table_open_cache
条目的级别。服务器在启动时会自动调整缓存大小。要显式设置大小,请在启动时设置 table_open_cache
系统变量。如本节后面所述,MySQL 可能会暂时打开比这更多的表来执行查询。
在以下情况下,MySQL 会关闭未使用表并将其从表缓存中删除
当缓存已满,并且线程尝试打开不在缓存中的表时。
当缓存包含超过
table_open_cache
个条目,并且缓存中的表不再被任何线程使用时。当发生表刷新操作时。当有人发出
FLUSH TABLES
语句或执行 mysqladmin flush-tables 或 mysqladmin refresh 命令时,就会发生这种情况。
当表缓存填满时,服务器使用以下过程来查找要使用的缓存条目
从最不最近使用的表开始,释放当前未使用的表。
如果必须打开新表,但缓存已满且无法释放任何表,则根据需要临时扩展缓存。当缓存处于临时扩展状态并且表从使用状态变为未使用状态时,表将关闭并从缓存中释放。
每个并发访问都会打开一个MyISAM
表。这意味着如果两个线程访问同一张表,或者如果一个线程在同一查询中两次访问同一张表(例如,通过将表自身连接起来),则需要打开两次表。每次并发打开都需要在表缓存中占用一个条目。任何MyISAM
表的第一次打开需要两个文件描述符:一个用于数据文件,另一个用于索引文件。表每次额外的使用只需要一个用于数据文件的文件描述符。索引文件描述符由所有线程共享。
如果使用HANDLER
语句打开一个表,则会为该线程分配一个专门的表对象。此表对象不会被其他线程共享,并且不会在该线程调用tbl_name
OPENHANDLER
或线程终止之前关闭。发生这种情况时,表将被放回表缓存中(如果缓存未满)。请参阅第 15.2.5 节,“HANDLER 语句”。tbl_name
CLOSE
要确定您的表缓存是否太小,请检查Opened_tables
状态变量,它指示自服务器启动以来的表打开操作次数。
mysql> SHOW GLOBAL STATUS LIKE 'Opened_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Opened_tables | 2741 |
+---------------+-------+
如果该值非常大或增长很快,即使您没有发出很多FLUSH TABLES
语句,也要在服务器启动时增加table_open_cache
值。