10.4.3.1 MySQL 打开和关闭表
当您执行mysqladmin status命令时,您应该看到类似以下内容:
Uptime: 426 Running threads: 1 Questions: 11082
Reloads: 1 Open tables: 12
Open tables
值为 12 可能会让您感到困惑,如果您有少于 12 个表。
MySQL 是多线程的,因此可能有许多客户端同时对同一个表进行查询。为了减少多个会话对同一个表的不同状态,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 节,“File Not Found and Similar Errors”。
表缓存的大小被设置为table_open_cache
项的数量。服务器在启动时自动调整缓存大小。要设置缓存大小,可以在启动时设置table_open_cache
系统变量。MySQL可能会在执行查询时临时打开更多的表,以后在本节中描述。
MySQL在以下情况下关闭未使用的表并将其从表缓存中删除:
-
当缓存已满且线程尝试打开不在缓存中的表时。
-
当缓存中包含超过
table_open_cache
项的表,并且缓存中的表不再被任何线程使用时。 -
当表刷新操作发生。这可能发生在某人执行
FLUSH TABLES
语句或执行mysqladmin flush-tables或mysqladmin refresh命令时。
当表缓存满时,服务器使用以下过程来找到可用缓存项:
-
当前不在使用的表将被释放,开始从最近最少使用的表中。
-
如果需要打开新的表,但缓存已满且无法释放表,则缓存将临时扩展到必要的程度。当缓存处于临时扩展状态且表从使用状态变为未使用状态时,表将被关闭并从缓存中释放。
一个MyISAM
表将为每个并发访问打开。这个意味着对同一个表的两个线程或同一个查询中的两个表访问都需要打开两次。每个并发打开都需要一个表缓存项。第一个打开任何MyISAM
表的操作需要两个文件描述符:一个用于数据文件和一个用于索引文件。每个额外的表打开操作只需要一个文件描述符用于数据文件。索引文件描述符将被所有线程共享。
如果您使用HANDLER语句打开一个表,一个专门的表对象将被分配给线程。这张表对象不被其他线程共享,直到线程调用HANDLER语句或线程终止。这个时候,表将被放回表缓存中(如果缓存不满)。请参阅Section 15.2.5, “HANDLER Statement”。
要确定您的表缓存是否太小,可以检查Opened_tables
状态变量,该变量表示服务器启动以来打开表的次数:
mysql> SHOW GLOBAL STATUS LIKE 'Opened_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Opened_tables | 2741 |
+---------------+-------+
如果值非常大或增长速度很快,即使您还没有发出许多FLUSH TABLES
语句,服务器启动时增加table_open_cache
值。