首页/数据/数据库速查/表缓存与打开文件数(table_open_cache)
性能与调优57 条

表缓存与打开文件数(table_open_cache)

缓存已打开表定义与文件句柄;Opened_tables 持续快速增长说明缓存不够或存在大量临时表,配合 open_files_limit 一起调。

数据库速查数据更新于 2026-10-13

表缓存缓存的是什么

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 参数而不改服务单元或内核限制,设置不会真正生效。

易错点

  • 只调 table_open_cache 不调 table_definition_cache:字典缓存不足时表定义仍会反复加载,问题依旧
  • 忽略操作系统句柄上限:几千张表的实例在运行中出现 too many open files,应用连接随机报错
  • 把 Opened_tables 的累计值当成当前问题:它是累计量,要看单位时间的增量才说明现状
  • 频繁 DDL 却期待缓存一直命中:表结构变更会让相关缓存失效,属预期行为而非参数配置错误

数据来源与参考

  • MySQL 8.0 Reference Manual: table_open_cache

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌