表缓存缓存的是什么
table_open_cache 决定实例能同时缓存多少张已打开表的定义与文件句柄。命中缓存时打开表几乎无成本,未命中就要走一次真实打开,涉及系统调用与元数据读取。分库分表环境动辄上千张表,该值偏小会让打开表的动作反复发生,表现为 CPU 占用偏高、目录扫描频繁,甚至报 too many open files。
基本信息
| 适用平台 | MySQL 5.7 / 8.0、MariaDB |
|---|---|
| 相关参数 | table_open_cache、table_definition_cache、open_files_limit |
| 观察指标 | Open_tables、Opened_tables、Open_table_definitions |
| 系统限制 | 受 systemd 的 LimitNOFILE 与内核 fs.file-max 约束 |
| 调整方式 | SET GLOBAL(即时)或写入配置文件(持久) |
典型使用场景
- 分库分表实例表数量多,CPU 偏高但慢查询不多
- Opened_tables 持续快速增长,怀疑表缓存容量不足
- 应用报 too many open files,需要同时排查缓存与系统句柄上限
- 迁移到新机器后性能变差,核对运行参数与句柄上限差异
- 大表 DDL 频繁执行导致表定义缓存反复失效
状态查看与调整
状态查看与调整
-- 当前打开与累计打开次数
SHOW STATUS LIKE 'Open%';
SHOW STATUS LIKE 'Opened_tables';
-- 相关缓存容量
SHOW VARIABLES LIKE 'table_open_cache';
SHOW VARIABLES LIKE 'table_definition_cache';
SHOW VARIABLES LIKE 'open_files_limit';
-- 动态调整缓存大小(重启后失效,需写入配置)
SET GLOBAL table_open_cache = 4000;
-- 观察调整后 Opened_tables 的增速是否下降
SHOW STATUS LIKE 'Opened_tables';关键指标读法
| 指标 | 含义 | 判断 |
|---|---|---|
| Open_tables | 当前打开的表数量 | 长期接近上限说明缓存刚好或不足 |
| Opened_tables | 累计打开次数 | 单位时间增速快说明缓存不命中 |
| Open_table_definitions | 缓存的表定义数 | 受 table_definition_cache 控制 |
| open_files_limit | 实例可用的文件句柄上限 | 偏小会先于缓存成为瓶颈 |
| table_open_cache | 表缓存条数上限 | 按实例表数量与并发规模设定 |
表缓存不是越大越好:设得过大本身会占用内存,而且当表数量远小于缓存上限时收益趋于零,关键是让常用表的打开动作不再重复发生。
在 systemd 管理的发行版上,open_files_limit 常被服务单元的 LimitNOFILE 卡住:只调 MySQL 参数而不改服务单元或内核限制,设置不会真正生效。