1, 简介
MySQL 8.0 将数据库元信息都存放于 InnoDB 存储引擎表中, 在之前版本的 MySQL 中, 数据字典不仅仅存放于特定的存储引擎表中, 还存放于元数据文件, 非事务性存储引擎表中. 本文将会介绍 MySQL 8.0 对数据字典的改进, 以及改进带来的好处, 影响以及局限性.
2, 数据字典
2.1, 新版本之前的数据字典
数据字典是数据库重要的组成部分之一, 那么什么是数据字典? 数据字典包含哪些内容呢? 数据字典是对数据库中的数据, 库对象, 表对象等的元信息的集合. 在 MySQL 中, 数据字典信息内容就包括表结构, 数据库名或表名, 字段的数据类型, 视图, 索引, 表字段信息, 存储过程, 触发器等内容. MySQL INFORMATION_SCHEMA 库提供了对数据局元数据, 统计信息, 以及有关 MySQL server 的访问信息 (例如: 数据库名或表名, 字段的数据类型和访问权限等). 该库中保存的信息也可以称为 MySQL 的数据字典. 在 MySQL8.0 之前, MySQL 的数据字典信息, 并没有全部存放在系统数据库表中, 部分数据库数据字典信息存放于文件中, 其余的数据字典信息存放于数据字典库中 (INFORMATION_SCHEMA,mysql,sys). 例如表结构信息存放在. frm 文件中, 数据库表字段信息存放于 INFORMATION_SCHEMA 下的 COLUMNS 表中. 早期, 5.6 版本之前, MyISAM 是 MySQL 的默认存储引擎, 而作为 MyISAM 存储引擎, 它是没有数据字典的. 只有表结构信息记录在. frm 文件中. MySQL5.6 版本之后, 将 InnoDB 存储引擎作为默认的存储引擎. 在 InnoDB 存储引擎中, 添加了一些数据字典文件用于存放数据字典元信息, 例如:.opt 文件, 记录了每个库的一些基本信息, 包括库的字符集等信息,.TRN,.TRG 文件用于存放触发器的信息内容.
2.2, 新版本数据字典的改进
最新的 MySQL 8.0 发布之后, 对数据库数据字典方面做了较大的改进.
首先是, 将所有原先存放于数据字典文件中的信息, 全部存放到数据库系统表中, 即将之前版本的. frm,.opt,.par,.TRN,.TRG,.isl 文件都移除了, 不再通过文件的方式存储数据字典信息.
其次是对 INFORMATION_SCHEM,mysql,sys 系统库中的存储引擎做了改进, 原先使用 MyISAM 存储引擎的数据字典表都改为使用 InnoDB 存储引擎存放. 从不支持事务的 MyISAM 存储引擎转变到支持事务的 InnoDB 存储引擎, 为原子 DDL 的实现, 提供了可能性.
3, 新数据字典带来的影响
3.1,INFORMATION_SCHEMA 性能提升
8.0 中对数据字典进行改进之后, 很大程度上提高了对 INFORMATIONS_SCHEMA 的查询性能, 通过可以通过查表快速的获得想要查询的数据, 原因是:
数据库在查询 INFORMATION_SCHEMA 的表时, 不再一定需要创建一张临时表, 可以直接查询数据字典表.
在之前版本中, 数据字典信息不一定是存放于表中, 所以在获取数据字典信息时候, 不仅仅是查表操作. 例如读取数据库表结构信息, 底层其实是读取. frm 文件来获得, 是一个文件打开读取的操作. 而在新版本中, 数据字典信息都可以通过直接查表的方式获取, 替代那些获取信息慢的方式.
对存储引擎的改进之后, 在查询 INFORMATIONS_SCHEMA 表时, 如果表上有索引, 优化器会合理的利用索引.
对于 INFORMATION_SCHEMA 下的 STATISTICS 表和 TABLES 表中的信息, 8.0 中通过缓存的方式, 以提高查询的性能. 可以通过设置 information_schema_stats_expiry 参数设置缓存数据的过期时间, 默认是 86400 秒. 查询这两张表的数据的时候, 首先是到缓存中进行查询, 缓存中没有缓存数据, 或者缓存数据过期了, 查询会从存储引擎中获取最新的数据. 如果需要获取最新的数据, 可以通过设置 information_schema_stats_expiry 参数为 0 或者 ANALYZE TABLE 操作.
3.2, 原子 DDL
MySQL8.0 开始支持原子 DDL 操作, 一个原子 DDL 操作, 具体的操作内容包括: 数据字典更新, 存储引擎层的操作, 在 binlog 中记录 DDL 操作. 并且这些操作都是原子性的, 表示中间过程出现错误的时候, 是可以完整回退的. 这在之前版本的 DDL 操作中是不支持的. 之前数据库版本中一直没有支持原子 DDL 的特性, 是有原因的, 因为在早期的数据库版本中, 数据库元信息存放于元信息文件中, 非事务性表中以及特定存储引擎的数据字典中. 这些都无法保证 DDL 操作内容在一个事务当中, 无法保证原子性. 具体的原子 DDL, 后续会有专门的文章.
3.3,innodb_read_only 对所有存储引擎生效
在 8.0 之前版本中, innodb_read_only 参数可以阻止对 InnoDB 存储引擎表的 create 和 drop 等更新操作. 但是在 MySQL8.0 中, 开启 innodb_read_only 参数阻止了所有存储引擎的这些操作. create 或者 drop 表的操作都需要更新数据字典表, 8.0 中这个数据字典表都改为了 InnoDB 存储引擎, 所以对于数据字典表的更新会失败, 从而导致各存储引擎 create 和 drop 表失败. 同样的像 ANALYZE TABLE 和
ALTER TABLE tbl_name ENGINE=engine_name
这种操作也会失败, 因为这些操作都要去更新数据字典表.
3.4,mysqldump mysqlpump 导出的内容影响
MySQL8.0 之后, 在使用 mysqldump 和 mysqlpump 导出数据时候, 与之前有了一些不同, 主要是以下几点:
之前版本的 mysqldump 和 mysqlpump 可以导出 mysql 系统库中的所有表的内容, 8.0 之后, 只能导出 mysql 系统库中的非 data dictionary table.(data dictionary table 内容可以参照: https://dev.mysql.com/doc/refman/8.0/en/system-database.html#system-database-data-dictionary-tables)
之前版本当使用 --all-databases 参数导出数据的时候, 不加 --routines 和 --events 选项也可以导出触发器, 存储过程等信息, 因为这些信息都存放于 proc 和 event 表中, 导出所有表即可导出这些信息. 但是在 8.0 中, proc 表和 event 表都不再使用, 并且定义触发器, 存储过程的数据字典表不会被导出, 所以在 8.0 中使用 mysqldump,mysqlpump 导出数据的时候, 如果需要导出触发器, 存储过程等内容, 一定需要加上 --routines 和 --events 选项.
之前版本中 --routines 选项导出的时候, 备份账户需要有 proc 表的 SELECT 权限, 在 8.0 中需要对所有表的 SELECT 权限
之前版本中, 导出触发器, 存储过程可以同时导出触发器, 存储过程的创建和修改的时间戳, 8.0 中不再支持.
3.5, 新数据字典的局限性
MySQL8.0 数据字典的改进有很多方便的特性, 例如带来了原子 DDL, 提升了 INFORMATION_SCHEMA 的查询性能等, 但是它并不是完美的, 新版数据字典还是存在一些局限性:
通过手动 mkdir 的方式在数据目录下创建库目录, 这种方式是不会被数据库所识别到.
DDL 操作会花费更长的时间, 因为之前的 DDL 操作是直接对. frm 文件进行更改操作, 只要写一个文件, 现在是需要更新数据字典表, 代表着需要将数据写到存储引擎, read log,undo log 中.
4, 总结
目前已经正式 GA 的 MySQL 8.0 是令人很期待的一个版本, 从数据字典方面的改进, 到原子 DDL, 到数据库 self tuning 等等新特性, 都让人为 8.0 感到激动. 8.0 中有许多新特性等待去尝试, 去发现.
来源: https://juejin.im/post/5b75976851882533122e1f5d