当您执行 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
的值。