search 2013 adfgs
作者:Sky.Jian | 可以任意转载, 但转载时务必以超链接形式标明文章原始出处 和 作者信息 及 版权声明
链接:http://isky000.com/database/mysql-8-innodb-dict | del.icio.us | Twitter it

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
    }
}

 

新的Information Schema定义

一些新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

目前表的元数据信息缓存在statisticstables表中以加速对IS表的查询性能。你可以通过参数information_schema_stats来直接读取已经缓存到内存的数据(cached),还是从存储引擎中获取最新的数据(latest). 很显然后者要慢一点。

而从is库下,可以看到对应两种表:TABLESTABLES_DYNAMIC, 以及STATISTICSSTATISTICS_DYNAMIC。当被设置为LATEST时,就会去从**_DYNAMIC表中去读取数据。

该选项也会影响到SHOW TABLES等语句的行为。

Data Dictionary Cache

数据词典的结构发生巨大的变化后,相应的对于内存数据词典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.

系统表变化

  • 和权限相关的表转换成InnoDB引擎
    • 包括:user, db, tables_priv, columns_priv, procs_priv, proxies_priv
  • func表转换成InnoDB事务表
    • 基于此变化,对function的操作(例如CREATE FUNCTION或者DROP FUNCTION, 或者用户定义的UDF)可能会导致一次隐式提交
  • mysql库下的routine表及event表不再使用,这些信息被存储到新的DD table中,并且在mysql库下是不可见的。
  • 外键系统表
    • 使用两个不可见的系统表foreign_keys和foreign_key_column_usage来存储外键信息 // 由于这两个系统表不可见,你需要通过IS库下的REFERENTIAL_CONSTRAINTS和KEY_COLUMN_USAGE表来获得外键信息 // 引入的不兼容:foreign key的名字不可以超过64个字符(之前版本是允许的)

看完了要说点啥么?