MySQL Data Dictionary 详解

MySQL Data Dictionary 详解
最新回答
净雅

2021-08-12 05:04:57

在 MySQL 8.0 之前,Server 层和存储引擎(例如 InnoDB)各自保留元数据,如 schema 名称、表定义等,导致信息存储重复冗余,且存在元数据不同步的问题。不同引擎间元数据存储形式和位置的差异(如.FRM, .PAR, .OPT, .TRN and .TRG 文件)使得元数据管理分散且复杂。将元数据存放在不支持事务的表和文件中,使 DDL 变更非原子,增加了崩溃恢复的难度。为解决这些挑战,MySQL 8.0 引入了 data dictionary,实现统一的元数据管理。

data dictionary 通过 Server 层和引擎层共享的 InnoDB 引擎表存储元数据,支持原子性操作,有效避免了元数据不同步的问题。它提供统一的 client API,包括元数据的基本操作(如获取、删除、存储、更新)。底层实现包括对 InnoDB 引擎数据字典表的读写操作,以及两级缓存加速内存访问,提高性能。

在内存和引擎层面,data dictionary 的数据结构遵循多态和接口/实现设计模式。Table_impl 是一个常访问的内存结构,包含表相关的元数据属性,如基本引擎类型、注释、分区类型等。Table_impl 还集成列信息、索引信息和分区信息等复杂属性,这些属性来自其他 DD 表。Column_impl 和 Partition_impl 分别表示列和分区的元信息,与 Table_impl 联系。

Table_impl 的持久化存储和访问通过 DD tables 实现,这些表存储在 mysql 表空间中,用户可通过 INFORMATION SCHEMA 查看部分视图。获取表元信息时,会调用 Storage_adapter::get() 接口,该接口根据 Tables 对象的枚举类型下标查找表定义中的列。

data dictionary 实现了两级缓存:一级是客户端本地的缓存,用于加速对相同对象的重复访问;二级是多线程共享的缓存,确保所有线程可访问并处理并发访问。缓存底层统一基于哈希表实现。

局部缓存位于每个 Dictionary_client 内部,管理不同类型的对象缓存,包含 committed、uncommitted 和 dropped 状态的对象。共享缓存是全局唯一的,通过 Shared_dictionary_cache 实现,包含针对各种类型对象的缓存。

缓存获取过程从一级局部缓存到二级共享缓存,最后到存储引擎。在缓存中获取时,优先查找 uncommitted 和 dropped 的 registry,然后是 committed registry,如果未找到,则从存储引擎加载。

在缓存 miss 的处理中,共享缓存会加锁后进行 hash map 查找,若存在则增加引用计数并返回;若不存在,则从存储引擎加载并加入缓存。并发控制通过广播和等待机制实现。

Auto_releaser 类用于确保在作用域内获取的 DD cache 对象不被释放,通过链式管理在不同层次间转移释放需求。在 DDL 过程中,通过 data dictionary 完成表定义的删除和存储。

总结而言,MySQL data dictionary 通过统一的管理、高效的缓存机制和原子性操作,显著提高了元数据的管理效率和安全性,简化了跨层访问的复杂性。