MySQL 8作为目前正在开发的最新版本,目前已经发布了DMR版本,这篇文章主要介绍 MySQL 8 的新特性之一:InnoDB数据字典。 MySQL的核心架构采用统一Server层+不同的底层引擎插件的架构模式,在Server层为每个表创建了frm文件,以保存与表定义相关的元数据信息。但有些引擎(例如InnoDB)本身也会存储元数据,这样不仅产生了元数据冗余,并且Server层和引擎层分别各自管理,在DDL之类的操作时,无法做到crash-safe,更别说让DDL具备事务性了。 MySQL 8 为了解决这些问题(尤其是DDL无法做到atomic),尝试取消了FRM文件及其他server层的元数据文件(frm, par, trn, trg, isl,db.opt),所有的元数据都用InnoDB引擎进行存储, 另外一些诸如权限表之类的系统表也改用InnoDB引擎。 下面就针对MySQL 8 的这个特性做一些基本的测试,一探究竟。 先创建个新库,并在库下创建两个表来开启我们的测试
mysql> CREATE DATABASE mysql8test;
Query OK, 1 row affected (0.00 sec)
mysql> USE mysql8test
Database changed
mysql> CREATE TABLE t1 (a int primary key);
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t2 (a int primary key, b int);
Query OK, 0 rows affected (0.00 sec)
$ls -lh /data/mysqldata/mydata/mysql8test/
total 256K
-rw-r----- 1 Sky users 128K Oct 5 19:44 t1.ibd
-rw-r----- 1 Sky users 128K Oct 5 19:44 t2.ibd
$cat /data/mysqldata/mydata/mysql8test_9.SDI
{
"sdi_version": 1,
"dd_version": 1,
"dd_object_type": "Schema",
"dd_object": {
"name": "mysqltest",
"default_collation_id": 33,
"created": 0,
"last_altered": 0
}
}
现在
库目录下只有ibd文件,并没有frm文件,而在数据目录下,相应的生成了一个SDI文件,来描述这个sbtest库的信息。
我们再来看看创建一个MYISAM引擎的表:
mysql> create database mysql8myisam;
Query OK, 1 row affected (0.00 sec)
mysql> use mysql8myisam
Database changed
mysql> create table t1 (a int, b varchar(320)) engine=myisam;
Query OK, 0 rows affected (0.00 sec)
$ls /data/mysqldata/mydata/mysql8myisam/
t1_435.SDI t1.MYD t1.MYI
$cat /data/mysqldata/mydata/mysql8myisam/t1_435.SDI
{
"sdi_version": 1,
"dd_version": 1,
"dd_object_type": "Table",
"dd_object": {
"name": "t1",
"mysql_version_id": 80000,
"created": 20161005201935,
"last_altered": 20161005201935,
"options": "avg_row_length=0;key_block_size=0;keys_disabled=0;pack_record=1;stats_auto_recalc=0;stats_sample_pages=0;",
"columns": [
{
"name": "a",
"type": 4,
"is_nullable": true,
"is_zerofill": false,
"is_unsigned": false,
"is_auto_increment": false,
"is_virtual": false,
"hidden": false,
"ordinal_position": 1,
"char_length": 11,
"numeric_precision": 10,
"numeric_scale": 0,
"datetime_precision": 0,
"has_no_default": false,
"default_value_null": true,
"default_value": "",
"default_option": "",
"update_option": "",
"comment": "",
"generation_expression": "",
"generation_expression_utf8": "",
"options": "interval_count=0;",
"se_private_data": "",
"column_key": 1,
"column_type_utf8": "int(11)",
"elements": [],
"collation_id": 33
},
{
"name": "b",
"type": 16,
"is_nullable": true,
"is_zerofill": false,
"is_unsigned": false,
"is_auto_increment": false,
"is_virtual": false,
"hidden": false,
"ordinal_position": 2,
"char_length": 960,
"numeric_precision": 0,
"numeric_scale": 0,
"datetime_precision": 0,
"has_no_default": false,
"default_value_null": true,
"default_value": "",
"default_option": "",
"update_option": "",
"comment": "",
"generation_expression": "",
"generation_expression_utf8": "",
"options": "interval_count=0;",
"se_private_data": "",
"column_key": 1,
"column_type_utf8": "varchar(320)",
"elements": [],
"collation_id": 33
}
],
"schema_ref": "mysql8myisam",
"hidden": false,
"se_private_id": 18446744073709551615,
"engine": "MyISAM",
"comment": "",
"se_private_data": "",
"row_format": 2,
"partition_type": 0,
"partition_expression": "",
"default_partitioning": 0,
"subpartition_type": 0,
"subpartition_expression": "",
"default_subpartitioning": 0,
"indexes": [],
"foreign_keys": [],
"partitions": [],
"collation_id": 33
}
}
一些新IS表使用View进行了重新设计,主要包括这些表:
CHARACTER_SETS
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
KEY_COLUMN_USAGE
SCHEMATA
STATISTICS
TABLES
TABLE_CONSTRAINTS
VIEWS
#例如SCHEMATA
mysql> show create table information_schema.schemata\G
*************************** 1. row ***************************
View: SCHEMATA
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`SCHEMATA` AS select `cat`.`name` AS `CATALOG_NAME`,`sch`.`name` AS `SCHEMA_NAME`,`cs`.`name` AS `DEFAULT_CHARACTER_SET_NAME`,`col`.`name` AS `DEFAULT_COLLATION_NAME`,NULL AS `SQL_PATH` from (((`mysql`.`schemata` `sch` join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `col` on((`sch`.`default_collation_id` = `col`.`id`))) join `mysql`.`character_sets` `cs` on((`col`.`character_set_id` = `cs`.`id`))) where can_access_database(`sch`.`name`)
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.01 sec)
也就是说,虽然DD系统表被隐藏不可见了,但你依然可以通过视图获得大部分信息。这种方式实际上大大加快了IS表的查询速度,转换成物理表的查询后,将无需为每个IS表的查询创建临时表(临时表的操作包含了server层创建frm, 引擎层获取数据or需要锁保护的全局数据)。另外优化器也能为IS表的查询选择更好的执行计划(例如使用系统表上的索引进行查询)。
新选项: information_schema_stats: CACHED | LATEST
目前表的元数据信息缓存在statistics及tables表中以加速对IS表的查询性能。你可以通过参数information_schema_stats来直接读取已经缓存到内存的数据(cached),还是从存储引擎中获取最新的数据(latest). 很显然后者要慢一点。
而从is库下,可以看到对应两种表:TABLES及TABLES_DYNAMIC, 以及STATISTICS及STATISTICS_DYNAMIC。当被设置为LATEST时,就会去从**_DYNAMIC表中去读取数据。
该选项也会影响到SHOW TABLES等语句的行为。
数据词典的结构发生巨大的变化后,相应的对于内存数据词典Cache也做改动,
mysql> show variables like '%defin%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| schema_definition_cache | 256 |
| stored_program_definition_cache | 256 |
| table_definition_cache | 1400 |
| tablespace_definition_cache | 256 |
+---------------------------------+-------+
4 rows in set (0.00 sec)
tablespace_definition_cache: tablespace cache的大小,存储了tablespace的定义. 一个tablespace中可能包含多个table。 table_definition_cache: stored_program_definition_cache: 存储过程&&function的定义cache. schema_definition_cache: 存储schema定义的cache hardcode的字符集cache:
character set definition cache partition: Stores character set definition objects and has a hardcoded object limit of 256.
collation definition cache partition: Stores collation definition objects and has a hardcoded object limit of 256.