mysql table_cache设置_【MySQL】关于table cache的相关参数 【转】

本文详细解析MySQL中表缓存机制的工作原理,包括不同存储引擎下表打开时的文件描述符消耗情况,并通过实际测试验证相关状态变量的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、状态值和变量:

1.1

在MySQL的show status中有2个状态值:Open_tables和Opened_tables。这2个值代表的意思如下:

Open_tables  :代表当前打开表的数量。

Opened_tables:代表自从MySQL启动后,打开表的数量。

(1)对于myisam存储引擎,打开1张表需要2个文件描述符(一个.MYD文件,一个.MYI文件)。

(2)对于innodb存储引擎,开启表的独立表空间(innodb_file_per_table)打开1张表只需要1个文件描述符(一个.ibd文件)。

【MySQL Variable】

对于上面的状态值,对应的5.1.3版本后的MySQL变量参数为table_open_cache,而早期版本为:table_cache,该参数值的代表MySQL可以缓存的打开表时候的最大文件描述符。

1.2

Open_table_definitions  :代表当前缓存了多少.frm文件。

Opened_table_definitions:代表自从MySQL启动后,缓存了.frm文件的数量。

需要注意的是.frm文件是MySQL用于存放表结构的文件,对应myisam和innodb存储引擎都必须有的。

【MySQL Variable】

对于上面的状态值,对应的5.1.3版本后的MySQL变量参数为table_definition_cache,该参数值的代表MySQL可以缓存的表定义的数量。和前面的table cache不同的是,表定义的缓存占用空间很小,而且不需要使用文件描述符,也就是只要打开.frm文件,缓存表定义,然后就可以关闭.frm文件。

1.3

另外,还有2个状态值:Open_files和Opened_files。这2个值的意思同上类似:

Open_files  :代表当前打开的文件。对应存储引擎(如:innodb)使用存储引擎自己内部函数打开的话,这个值是不会增加的。

Opened_files:代表使用MySQL的my_open()函数打开过的文件数。如果不是使用这个函数打开文件的话,这个值是不会增加的。

【MySQL Variable】

对于上面的状态值,对应的MySQL变量参数为open_files_limit。

二、测试

测试的MySQL版本:

mysql> select version();

+------------+

| version()  |

+------------+

| 5.1.47-log |

+------------+

1 row in set (0.00 sec)

2.1 myisam存储引擎

2.1.1

重启MySQL服务器,可以看到启动时候MySQL已经自动打开相关的系统表。

mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| Open_table_definitions   | 15    |

| Opened_table_definitions | 15    |

+--------------------------+-------+

2 rows in set (0.00 sec)

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_tables   | 8     |

| Opened_tables | 15    |

+---------------+-------+

2 rows in set (0.00 sec)

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_files    | 19    |

| Opened_files  | 62    |

+---------------+-------+

2 rows in set (0.00 sec)

在上面的状态输出,可以看到Open_tables的值为8,代表了当前打开了8张表,同样的通过mysqladmin status命令也可以看到:

[mysql@xentest8-vm1 test]$ mysqladmin status

Uptime: 631  Threads: 2  Questions: 14  Slow queries: 0  Opens: 15  Flush tables: 1  Open tables: 8 Queries per second avg: 0.22

可以通过SHOW OPEN TABLES命令查看,当前的table cache到底打开了哪些表:

mysql>show open tables;

+----------+--------------+--------+-------------+

| Database | Table        | In_use | Name_locked |

+----------+--------------+--------+-------------+

| mysql    | servers      |      0 |           0 |

| mysql    | db           |      0 |           0 |

| mysql    | host         |      0 |           0 |

| mysql    | columns_priv |      0 |           0 |

| mysql    | user         |      0 |           0 |

| mysql    | procs_priv   |      0 |           0 |

| mysql    | event        |      0 |           0 |

| mysql    | tables_priv  |      0 |           0 |

+----------+--------------+--------+-------------+

8 rows in set (0.00 sec)

可以看到打开了mysql库里面的8张系统表(都是myisam存储引擎),另外,还可以通过lsof(lsof的用法参见)查看MySQL打开的对应文件:

[zhuxu@xentest8-vm1 ~]$ sudo lsof -u mysql | grep /home/mysql/mysql-5.1.47/data/mysql/

mysqld    14683 mysql   16u   REG              253,1      2048 87889757 /home/mysql/mysql-5.1.47/data/mysql/host.MYI

mysqld    14683 mysql   17u   REG              253,1         0 87889758 /home/mysql/mysql-5.1.47/data/mysql/host.MYD

mysqld    14683 mysql   18u   REG              253,1      2048 87889760 /home/mysql/mysql-5.1.47/data/mysql/user.MYI

mysqld    14683 mysql   19u   REG              253,1       380 87889761 /home/mysql/mysql-5.1.47/data/mysql/user.MYD

mysqld    14683 mysql   20u   REG              253,1      5120 87889754 /home/mysql/mysql-5.1.47/data/mysql/db.MYI

mysqld    14683 mysql   21u   REG              253,1       880 87889755 /home/mysql/mysql-5.1.47/data/mysql/db.MYD

mysqld    14683 mysql   22u   REG              253,1      4096 87889772 /home/mysql/mysql-5.1.47/data/mysql/tables_priv.MYI

mysqld    14683 mysql   23u   REG              253,1         0 87889773 /home/mysql/mysql-5.1.47/data/mysql/tables_priv.MYD

mysqld    14683 mysql   24u   REG              253,1      4096 87889775 /home/mysql/mysql-5.1.47/data/mysql/columns_priv.MYI

mysqld    14683 mysql   25u   REG              253,1         0 87889776 /home/mysql/mysql-5.1.47/data/mysql/columns_priv.MYD

mysqld    14683 mysql   26u   REG              253,1      4096 87889808 /home/mysql/mysql-5.1.47/data/mysql/procs_priv.MYI

mysqld    14683 mysql   27u   REG              253,1         0 87889809 /home/mysql/mysql-5.1.47/data/mysql/procs_priv.MYD

mysqld    14683 mysql   28u   REG              253,1      1024 87889769 /home/mysql/mysql-5.1.47/data/mysql/servers.MYI

mysqld    14683 mysql   29u   REG              253,1         0 87889770 /home/mysql/mysql-5.1.47/data/mysql/servers.MYD

mysqld    14683 mysql   30u   REG              253,1      2048 87889817 /home/mysql/mysql-5.1.47/data/mysql/event.MYI

mysqld    14683 mysql   31u   REG              253,1         0 87889818 /home/mysql/mysql-5.1.47/data/mysql/event.MYD

2.1.2

接着打开一张myisam存储引擎的表:

mysql> select count(*) from myisam_1;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (0.00 sec)

mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';

# 可以看到Opened_table_definitions/Opened_table_definitions/Open_tables/Opened_tables的值都加1

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| Open_table_definitions   | 16    |  +1

| Opened_table_definitions | 16  |  +1

+--------------------------+-------+

2 rows in set (0.00 sec)

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_tables   | 9     |  +1

| Opened_tables | 16 |  +1

+---------------+-------+

2 rows in set (0.00 sec)

# 可以看到Open_files的值(19+2)加2,Opened_files的值(62+3)加3

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_files    | 21    |+2(MYI,MYD)

| Opened_files  | 65  | +3(MYI,MYD,FRM)

+---------------+-------+

2 rows in set (0.00 sec)

mysql> show create table myisam_1\G

*************************** 1. row ***************************

Table: myisam_1

Create Table: CREATE TABLE `myisam_1` (

`a` int(11) DEFAULT NULL,

KEY `idx_myisam_1` (`a`)

) ENGINE=MyISAM DEFAULT CHARSET=latin1

1 row in set (0.00 sec)

mysql> show open tables from test;

+----------+----------+--------+-------------+

| Database | Table    | In_use | Name_locked |

+----------+----------+--------+-------------+

| test     | myisam_1 |      0 |           0 |

+----------+----------+--------+-------------+

1 row in set (0.00 sec)

[zhuxu@xentest8-vm1 ~]$ sudo lsof-u mysql | grep /home/mysql/mysql-5.1.47/data/test/

mysqld    14683 mysql  33u REG              253,1      1024 87851510 /home/mysql/mysql-5.1.47/data/test/myisam_1.MYI

mysqld    14683 mysql   34u REG              253,1         0 87851511 /home/mysql/mysql-5.1.47/data/test/myisam_1.MYD

# 可见,除了需要打开.frm文件(打开,缓存后,就关闭,所以Open_files没有+3,只有+2),对于myisam存储引擎,打开1张表需要2个文件描述符(一个.MYD文件,一个.MYI文件)

2.1.3

对应table cache中的缓存的表,可以通过flush tables命令来把它人工移出table cache:

mysql>flush tables myisam_1;

Query OK, 0 rows affected (0.00 sec)

mysql> show open tables from test;

Empty set (0.00 sec)

mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';

# 可以看到Open_table_definitions和Open_tables的值都减1

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| Open_table_definitions   | 15    | -1

| Opened_table_definitions | 16    |

+--------------------------+-------+

2 rows in set (0.00 sec)

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_tables   | 8     | -1

| Opened_tables | 16    |

+---------------+-------+

2 rows in set (0.00 sec)

# 可以看到Open_files的值(21-2)减2

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_files    | 19    |-2 (MYI,MYD)

| Opened_files  | 65 |

+---------------+-------+

2 rows in set (0.00 sec)

[zhuxu@xentest8-vm1 ~]$ sudo lsof -u mysql | grep /home/mysql/mysql-5.1.47/data/test/ | wc -l

0

2.2 innodb存储引擎

2.2.1

打开一张innodb存储引擎的表:

mysql> show variables like 'innodb_file_per_table';

+-----------------------+-------+

| Variable_name         | Value |

+-----------------------+-------+

| innodb_file_per_table | ON    |

+-----------------------+-------+

1 row in set (0.00 sec)

mysql> select count(*) from t0001;

+----------+

| count(*) |

+----------+

|        2 |

+----------+

1 row in set (0.01 sec)

mysql> show global status like 'Open%_table_definitions';show global status like 'Open%_tables';show global status like 'Open%_files';

# 可以看到Opened_table_definitions/Opened_table_definitions/Open_tables/Opened_tables的值都加1

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| Open_table_definitions   | 16    | +1

| Opened_table_definitions | 17  | +1

+--------------------------+-------+

2 rows in set (0.00 sec)

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_tables   | 9     | +1

| Opened_tables | 17 | +1

+---------------+-------+

2 rows in set (0.00 sec)

# 可以看到Open_files的值不变(即innodb使用存储引擎自己内部函数打开的话,这个值是不会增加)

# Opened_files的值(65+1)加1(需要打开.frm文件,缓存后,就关闭)

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_files    | 19    | +0

| Opened_files  | 66  | +1

+---------------+-------+

2 rows in set (0.00 sec)

mysql> show open tables from test;

+----------+-------+--------+-------------+

| Database | Table | In_use | Name_locked |

+----------+-------+--------+-------------+

| test     | t0001 |      0 |           0 |

+----------+-------+--------+-------------+

1 row in set (0.00 sec)

mysql> show create table t0001\G

*************************** 1. row ***************************

Table: t0001

Create Table: CREATE TABLE `t0001` (

`a` int(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=latin1

1 row in set (0.00 sec)

[zhuxu@xentest8-vm1 ~]$ sudo lsof -u mysql | grep /home/mysql/mysql-5.1.47/data/test/

mysqld    14683 mysql   33uW REG              253,1     98304 87851074 /home/mysql/mysql-5.1.47/data/test/t0001.ibd

2.2.2

对于innodb存储引擎,table cache对其影响其实不是很大,innodb有自己的数据字典,可以缓存相关表信息。

PS:

<think>我们正在讨论如何正确配置MySQLtable_open_cache参数。根据引用内容,table_open_cacheMySQL中一个重要的参数,它决定了可以同时打开的表的数量。如果设置过小,可能会导致频繁打开关闭表,影响性能;如果设置过大,可能会占用过多资源,甚至导致文件描述符不足。根据引用[1]:默认的table_open_cache为64,这个数值通常偏小,尤其在高连接数(max_connections较大)的情况下容易引起性能问题。可以通过观察状态变量`Opened_tables`(表示打开表的次数)`Open_tables`(表示当前打开表的数量)来判断是否需要调整。如果`Opened_tables`的值很大且持续增长,说明需要增大table_open_cache。引用[1]还提到,一般建议将table_open_cache设置为max_connections的值(或者乘以每个查询中平均涉及的表数)。例如,如果max_connections为100,每个查询平均涉及2个表,那么可以设置为200。但实践中,设置为max_connections的值通常就足够了。引用[5]提到,设置过大可能会遇到文件描述符不足的问题(错误23或24)。这时需要调整open_files_limit参数(增加mysqld可打开的文件数)或者减小table_open_cache或max_connections。另外,引用[4]提到,MySQL将全局的tablecache划分为多个Table_cacheinstance,由参数table_open_cache_instances控制。这个参数MySQL5.6.6及更高版本中引入,用于减少锁竞争。每个instance负责一部分tablecache,用户线程根据thread_id选择instance。通常,建议将table_open_cache_instances设置为1到16之间,但具体设置需要根据实际情况调整。配置步骤:1.查看当前设置:```sqlSHOWVARIABLESLIKE'table_open_cache';SHOWVARIABLESLIKE'max_connections';SHOWVARIABLESLIKE'table_open_cache_instances';```2.查看状态以判断当前设置是否合理:```sqlSHOWGLOBALSTATUSLIKE'Open%tables';```如果`Open_tables`接近table_open_cache,并且`Opened_tables`持续增长,说明需要增大table_open_cache。3.设置新的值(例如设置为1024):```sqlSETGLOBALtable_open_cache=1024;```注意:这个设置是临时的,重启后会失效。要永久生效,需要在MySQL配置文件(如my.cnf或my.ini)中添加或修改:```[mysqld]table_open_cache=1024```4.同时,如果遇到文件描述符不足的问题,需要调整open_files_limit。在配置文件中设置:```[mysqld]open_files_limit=65535```注意:open_files_limit的值应该大于table_open_cache的值(因为MySQL还需要打开其他文件)。5.关于table_open_cache_instances,通常默认值(例如8)在大多数情况下是合适的。如果需要调整,可以在配置文件中设置:```table_open_cache_instances=8```6.修改配置文件后,需要重启MySQL服务。总结:配置table_open_cache的关键是观察`Opened_tables`的状态,将其调整到一个合理的值,避免频繁打开表。同时注意与max_connectionsopen_files_limit的协调。注意:每个系统的情况不同,调整后需要观察性能变化。根据上述内容,生成相关问题:1.如何监控table_open_cache是否设置合理?2.调整table_open_cache后,如何验证效果?3.除了table_open_cache,还有哪些与表缓存相关参数?4.文件描述符不足时,除了调整open_files_limit,还可以如何处理?</think>### 如何正确配置MySQLtable_open_cache参数 配置MySQL的`table_open_cache`参数需综合考虑系统资源、连接数表使用情况,以下是具体步骤: #### 1. **诊断当前状态** ```sql -- 查看当前缓存设置 SHOW VARIABLES LIKE 'table_open_cache'; -- 检查表打开状态(关键指标) SHOW GLOBAL STATUS LIKE 'Open%tables'; ``` - **Open_tables**:当前打开的表数量(理想值应接近`table_open_cache`)[^1] - **Opened_tables**:累计打开次数(值过高说明缓存不足)[^1] 示例诊断: ``` +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Open_tables | 345 | -- 建议接近table_open_cache值 | Opened_tables | 9,734,116 | -- 过高说明频繁重新打开表 +---------------+-------+ ``` #### 2. **计算合理值** - **基础公式**: ```math \text{推荐值} = \text{max\_connections} \times \text{平均每查询涉及表数} ``` 实践中可简化为: ```math \text{推荐值} \approx \text{max\_connections} \quad [^1] ``` - **上限约束**: 需满足: ```math \text{table\_open\_cache} < \text{open\_files\_limit} - 100 \quad [^5] ``` #### 3. **动态调整** ```sql -- 临时生效(无需重启) SET GLOBAL table_open_cache = 1024; ``` 修改后立即监控`Opened_tables`增长速率是否下降[^1]。 #### 4. **永久生效配置** 在`my.cnf`中添加: ```ini [mysqld] table_open_cache = 1024 # 建议值为max_connections的1-1.5倍 table_open_cache_instances = 8 # 减少锁竞争[^4] open_files_limit = 65535 # 必须大于table_open_cache[^5] ``` #### 5. **优化验证** - 观察指标: - `Opened_tables`增速显著降低 - `SHOW PROCESSLIST`中`Opening tables`状态减少[^1] - 错误处理: 若出现`Can't open file (errno: 24)`,需增加`open_files_limit`[^5] #### 6. **注意事项** - 避免极端值:过大会消耗内存,过小导致性能瓶颈[^3] - 多实例配置:高并发时`table_open_cache_instances`应设为CPU核心数[^4] - 表统计:复杂查询涉及多表时需适当增大缓存 > **配置示例**: > 若`max_connections=500`且无文件限制问题: > ```math > \text{table\_open\_cache} = 500 \sim 750 > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值