我们在 第12问 中介绍了 table cache 的作用:在同一个线程内,减少了重复读取表定义的成本,包括读取表定义文件的 IO 成本, 和 构造内存结构的 CPU 成本。(要注意 table cache 是线程级别的)
同时我们发现了一个问题,即使没有命中 table cache ,MySQL 也不一定会从表定义文件中读取。
这就是因为命中了 table definition cache (之后我们简称为 TDC),TDC 是全局级别的表定义缓存
本期我们就来介绍一下 table definition cache 的作用
我们的实验方法与 第12问 相同
构造一个数据库:
我们将 TDC 设置为最小值 400:
现在使用 sysbench,来构造500张表:
现在使用 strace 监听 MySQL 的 IO 操作:
接下来我们将逐一访问刚才造出来的500张表,我们先需要生成一个脚本:
我们从 information_schema 中,读取表名,并拼出相关的 SQL
现在就可以执行脚本了,我们将刚才生成的 SQL 通过管道符导入 MySQL client 进行执行:
观察 strace 的输出:
会发现 MySQL 在不停打开 frm 文件,来读取各个表的定义
我们现在调大 TDC的大小,再进行一次实验:
重做试验,我们会发现 strace 没有新的输出:MySQL 不再反复读取 frm 文件
这就是 TDC 的作用:在全局级别建立一个缓存,用于减少读取表定义的成本。
思考题 此处我们留一个思考题: 我们将 TDC 设置为400,在实验中我们通过脚本访问了500张表, 这个实验可以反复进行。 但每次 strace 都会显示 MySQL 访问了500个 frm 文件, 仿佛 TDC 并没有起作用一样。 请大家思考:这个现象是什么原因?
如果我们在MySQL 8.0中,重复以上实验,会发现 MySQL 也不再读取 frm 文件。
这是因为 MySQL 8.0 引入了 Data Dictionary ,将表定义放在了表中,不再需要访问 frm 文件。
如果 TDC 溢出, 并不会像 table_cache 溢出那样, 会有相关的状态量来显示 (table_open_cache_overflows)。
为了不让 TDC 带来的好处消失, 我们建议始终保持 状态 Opened_table_definitions 小于参数 table_definition_cache , 这样就能保证 TDC 始终命中。
而我们付出的只有一点点内存的代价, 利大于弊。
本文关键字:#mysql# #cache#