当您执行 mysqladmin 状态 命令时,您应该看到类似以下内容:
Uptime: 426 Running threads: 1 Questions: 11082
Reloads: 1 Open tables: 12
“Open tables” 值为 12 可能会让您感到困惑,如果您只有少于 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
值在服务器启动时。