我们在 第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 的技术内容,你们还有什么想知道的吗?赶紧留言告诉小编吧!

分类: 技术文章

avatar
100
  Subscribe  
提醒