MySQL InnoDB INFORMATION_SCHEMA系统表

InnoDB INFORMATION_SCHEMA系统表
你可以使用InnoDB INFORMATION_SCHEMA系统表来提取由InnoDB管理的schema对象的元数据。这些信息来自InnoDB内部的系统表(也称为InnoDB数据字典),它不能像普通的InnoDB表那样直接查询。传统上,你可以使用InnoDB监视器技术来获取这类信息,设置InnoDB监视器并解析SHOW ENGINE InnoDB STATUS语句的输出。InnoDB INFORMATION_SCHEMA表接口允许你使用SQL查询这些数据。

除了INNODB_SYS_TABLESTATS没有对应的内部系统表外,InnoDB INFORMATION_SCHEMA系统表中的数据都是直接从InnoDB内部系统表中读取的,而不是从内存中缓存的元数据中读取。

InnoDB INFORMATION_SCHEMA系统表包括下面列出的表。INNODB_SYS_DATAFILES和INNODB_SYS_TABLESPACES是在MySQL 5.6.6中添加的,引入了对CREATE TABLE语句中的DATA DIRECTORY=’ DIRECTORY ‘子句的支持,它允许InnoDB file-per-table表空间(在MySQL数据目录之外的位置创建ibd文件。

mysql> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_SYS%';
+--------------------------------------------+
| Tables_in_information_schema (INNODB_SYS%) |
+--------------------------------------------+
| INNODB_SYS_DATAFILES                       |
| INNODB_SYS_VIRTUAL                         |
| INNODB_SYS_INDEXES                         |
| INNODB_SYS_TABLES                          |
| INNODB_SYS_FIELDS                          |
| INNODB_SYS_TABLESPACES                     |
| INNODB_SYS_FOREIGN_COLS                    |
| INNODB_SYS_COLUMNS                         |
| INNODB_SYS_FOREIGN                         |
| INNODB_SYS_TABLESTATS                      |
+--------------------------------------------+
10 rows in set (0.00 sec)

表名表明所提供的数据类型:
.INNODB_SYS_TABLES提供关于InnoDB表的元数据,等价于InnoDB数据字典中的SYS_TABLES表中的信息。

.INNODB_SYS_COLUMNS提供关于InnoDB表列的元数据,等价于InnoDB数据字典中的SYS_COLUMNS表中的信息。

.INNODB_SYS_INDEXES提供有关InnoDB索引的元数据,等价于InnoDB数据字典中的SYS_INDEXES表中的信息。

.INNODB_SYS_FIELDS提供了InnoDB索引中关键列(字段)的元数据,等价于InnoDB数据字典中的SYS_FIELDS表中的信息。

.INNODB_SYS_TABLESTATS提供了关于InnoDB表的底层状态信息的视图,这些状态信息来源于内存中的数据结构。没有对应的内部InnoDB系统表。

.INNODB_SYS_DATAFILES提供了InnoDB file-per-table件和一般表空间的数据文件路径信息,等价于InnoDB数据字典中的SYS_DATAFILES表中的信息。

.INNODB_SYS_TABLESPACES提供了关于InnoDB file-per-table和一般表空间的元数据,等价于InnoDB数据字典中的SYS_TABLESPACES表中的信息。

.INNODB_SYS_FOREIGN提供了定义在InnoDB表上的外键的元数据,等价于InnoDB数据字典中的SYS_FOREIGN表中的信息。

.INNODB_SYS_FOREIGN_COLS提供了定义在InnoDB表中的外键列的元数据,等价于InnoDB数据字典中的SYS_FOREIGN_COLS表中的信息。

InnoDB INFORMATION_SCHEMA系统表可以通过TABLE_ID、INDEX_ID和SPACE等字段连接在一起,让你可以轻松地检索到你想要研究或监控的对象的所有可用数据。

这个例子使用一个简单的表(t1)和一个索引(i1)来展示在InnoDB INFORMATION_SCHEMA系统表中发现的元数据的类型。
1.创建表t1:

mysql> use test;
Database changed
mysql> create table t1 (
    -> col1 int,
    -> col2 char(10),
    -> col3 varchar(10))
    -> engine = innodb;
Query OK, 0 rows affected (0.04 sec)

mysql> create index i1 on t1(col1);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

2.创建表t1后,查询innodb_sys_tables来定位test/t1的元数据:

mysql> select * from information_schema.innodb_sys_tables where name='test/t1' \G
*************************** 1. row ***************************
     TABLE_ID: 509
         NAME: test/t1
         FLAG: 33
       N_COLS: 6
        SPACE: 508
  FILE_FORMAT: Barracuda
   ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single
1 row in set (0.01 sec)

表t1的TABLE_ID是509。FLAG字段提供了有关表格式和存储特性的位级别信息。有6列,其中3列是由InnoDB创建的隐藏列(DB_ROW_ID, DB_TRX_ID和DB_ROLL_PTR)。表空间的ID是508(值为0表示表驻留在system表空间中)。FILE_FORMAT是Barracuda格式,ROW_FORMAT是Dynamic格式。ZIP_PAGE_SIZE只适用于行格式压缩的表。

3.使用innodb_sys_tables中的table_id信息,查询innodb_sys_columns表中关于表的列的信息。

mysql> select * from information_schema.innodb_sys_columns where table_id = 509 \G
*************************** 1. row ***************************
TABLE_ID: 509
    NAME: col1
     POS: 0
   MTYPE: 6
  PRTYPE: 1027
     LEN: 4
*************************** 2. row ***************************
TABLE_ID: 509
    NAME: col2
     POS: 1
   MTYPE: 13
  PRTYPE: 2949374
     LEN: 40
*************************** 3. row ***************************
TABLE_ID: 509
    NAME: col3
     POS: 2
   MTYPE: 12
  PRTYPE: 2949135
     LEN: 40
3 rows in set (0.00 sec)

除了TABLE_ID和NAME列之外,INNODB_SYS_COLUMNS还提供了每列的序号位置(POS)(从0开始,顺序递增),列的MTYPE或“主类型”(6 = INT,13 = CHAR, 12 = VARCHAR), PRTYPE或“精确类型”(一个二进制值,用比特表示MySQL的数据类型,字符集代码和可空性),以及列的长度(LEN)。

4.再次使用innodb_sys_tables中的table_id信息,查询innodb_sys_indexes,获取与表t1相关的索引信息。

mysql> select * from information_schema.innodb_sys_indexes where table_id = 509 \G
*************************** 1. row ***************************
       INDEX_ID: 758
           NAME: GEN_CLUST_INDEX
       TABLE_ID: 509
           TYPE: 1
       N_FIELDS: 0
        PAGE_NO: 3
          SPACE: 508
MERGE_THRESHOLD: 50
*************************** 2. row ***************************
       INDEX_ID: 759
           NAME: i1
       TABLE_ID: 509
           TYPE: 0
       N_FIELDS: 1
        PAGE_NO: 4
          SPACE: 508
MERGE_THRESHOLD: 50
2 rows in set (0.01 sec)

INNODB_SYS_INDEXES返回两个索引的数据第一个索引是GEN_CLUST_INDEX,如果表没有用户定义的聚集索引,它是由InnoDB创建的聚集索引。第二个索引(i1)是用户定义的辅助索引。

INDEX_ID是索引的标识符,在一个实例中的所有数据库中都是唯一的。TABLE_ID标识了索引关联的表。索引TYPE值指示索引类型(1 =集群索引,0 =辅助索引)。n_fields值是组成索引的字段数目。PAGE_NO是索引B-tree的根页号,SPACE是索引所在的表空间ID。非零值表示索引不在系统表空间中。MERGE_THRESHOLD定义索引页中数据量的百分比阈值。当删除一行或者更新操作缩短一行时,如果索引页中的数据量低于这个值(默认值为50%),InnoDB会尝试将索引页与相邻的索引页合并。

5.使用innodb_sys_indexes中的index_id信息,查询innodb_sys_fields中索引i1的字段信息。

mysql> select * from information_schema.innodb_sys_fields where index_id = 759 \G
*************************** 1. row ***************************
INDEX_ID: 759
    NAME: col1
     POS: 0
1 row in set (0.01 sec)

INNODB_SYS_FIELDS提供了索引字段的名称及其在索引中的序号位置。如果索引(i1)定义在多个字段上,INNODB_SYS_FIELDS将为每个被索引的字段提供元数据。

6.使用innodb_sys_tables中的space信息,查询innodb_sys_tables]表获得关于表的表空间信息。

mysql> select * from information_schema.innodb_sys_tablespaces where space = 508 \G
*************************** 1. row ***************************
         SPACE: 508
          NAME: test/t1
          FLAG: 33
   FILE_FORMAT: Barracuda
    ROW_FORMAT: Dynamic
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Single
 FS_BLOCK_SIZE: 4096
     FILE_SIZE: 114688
ALLOCATED_SIZE: 114688
1 row in set (0.05 sec)

除了表空间的SPACE ID和关联表的NAME之外,INNODB_SYS_TABLESPACES还提供了表空间的FLAG数据,这是有关表空间格式和存储特性的位级别信息。还提供了表空间FILE_FORMAT、ROW_FORMAT、PAGE_SIZE和其他几个表空间元数据项。

7.再次使用INNODB_SYS_TABLES中的SPACE信息,查询INNODB_SYS_DATAFILES表空间数据文件的位置。

mysql> select * from information_schema.innodb_sys_datafiles where space = 508 \G
*************************** 1. row ***************************
SPACE: 508
 PATH: ./test/t1.ibd
1 row in set (0.00 sec)

该数据文件位于MySQL的data目录下的test目录中。如果使用CREATE TABLE语句的data directory子句在MySQL数据目录之外的位置创建一个file-per-table表空间,那么表空间路径将是一个完全限定的目录路径。

8.最后一步,在表t1 (TABLE_ID = 509)中插入一行,然后查看INNODB_SYS_TABLESTATS表中的数据。MySQL优化器使用该表中的数据来计算查询InnoDB表时使用的索引。该信息来源于内存中的数据结构。没有对应的内部InnoDB系统表。

mysql> insert into t1 values(5, 'abc', 'def');
Query OK, 1 row affected (0.00 sec)

mysql> select * from information_schema.innodb_sys_tablestats where table_id = 509 \G
*************************** 1. row ***************************
         TABLE_ID: 509
             NAME: test/t1
STATS_INITIALIZED: Initialized
         NUM_ROWS: 1
 CLUST_INDEX_SIZE: 1
 OTHER_INDEX_SIZE: 1
 MODIFIED_COUNTER: 1
          AUTOINC: 0
        REF_COUNT: 2
1 row in set (0.00 sec)

STATS_INITIALIZED字段表示是否收集了表的统计信息。NUM_ROWS是表中当前估计的行数。cluster_index_size和OTHER_INDEX_SIZE字段分别报告磁盘上为表存储集群索引和辅助索引的页数。MODIFIED_COUNTER值显示了由DML操作和来自外键的级联操作修改的行数。AUTOINC值是任何基于自动递增操作的下一个数字。在表t1中没有定义autoincrement列,因此值为0。REF_COUNT值是一个计数器。当计数器变为0时,表示表元数据可以从表缓存中移除。

外键信息_schema系统表
INNODB_SYS_FOREIGN和INNODB_SYS_FOREIGN_COLS表提供了有关外键关系的数据。这个例子使用具有外键关系的父表和子表来展示在INNODB_SYS_FOREIGN和INNODB_SYS_FOREIGN_COLS表中找到的数据。

1.创建包含父表和子表的测试数据库:

mysql> create table parent (id int not null,
    -> primary key (id)) engine=innodb;
Query OK, 0 rows affected (0.03 sec)

mysql> create table child (id int, parent_id int,
    -> index par_ind (parent_id),
    -> constraint fk1
    -> foreign key (parent_id) references parent(id)
    -> on delete cascade) engine=innodb;
Query OK, 0 rows affected (0.01 sec)

2.在创建父表和子表之后,查询INNODB_SYS_FOREIGN并找到test/child和test/parent外键关系的外键数据:

mysql> select * from information_schema.innodb_sys_foreign \G
*************************** 1. row ***************************
      ID: test/fk1
FOR_NAME: test/child
REF_NAME: test/parent
  N_COLS: 1
    TYPE: 1

元数据包括外键ID (fk1),它是根据在子表上定义的约束命名的。FOR_NAME是定义外键的子表的名称。REF_NAME是父表(被引用的表)的名称。N_COLS是外键索引中的列数。TYPE是一个数值,表示提供有关外键列的附加信息的位标志。在本例中,TYPE值为1,表示为外键指定了ON DELETE CASCADE选项。有关类型值的更多信息,请参阅INNODB_SYS_FOREIGN表定义。

3.使用外键ID,查询INNODB_SYS_FOREIGN_COLS来查看这个外键对应的列的数据。

mysql> select * from information_schema.innodb_sys_foreign_cols where id = 'test/fk1' \G
*************************** 1. row ***************************
          ID: test/fk1
FOR_COL_NAME: parent_id
REF_COL_NAME: id
         POS: 0
1 row in set (0.00 sec)

FOR_COL_NAME是子表中外键列的名称,REF_COL_NAME是父表中被引用的列的名称。POS值是键字段在外键索引中的顺序位置,从0开始。

连接InnoDB INFORMATION_SCHEMA系统表
这个例子展示了连接三个InnoDB INFORMATION_SCHEMA系统表(INNODB_SYS_TABLES、INNODB_SYS_TABLESPACES和INNODB_SYS_TABLESTATS)来收集employees sample数据库中表的文件格式、行格式、页面大小和索引大小信息。

mysql> select a.name, a.file_format, a.row_format,
    -> @page_size :=
    -> if(a.row_format='compressed',
    -> b.zip_page_size, b.page_size)
    -> as page_size,
    -> round((@page_size * c.clust_index_size)
    -> /(1024*1024)) as pk_mb,
    -> round((@page_size * c.other_index_size)
    -> /(1024*1024)) as secidx_mb
    -> from information_schema.innodb_sys_tables a
    -> inner join information_schema.innodb_sys_tablespaces b on a.name = b.name
    -> inner join information_schema.innodb_sys_tablestats c on b.name = c.name
    -> where a.name like 'employees/%'
    -> order by a.name desc;
+------------------------+-------------+------------+-----------+-------+-----------+
| name                   | file_format | row_format | page_size | pk_mb | secidx_mb |
+------------------------+-------------+------------+-----------+-------+-----------+
| employees/titles       | Barracuda   | Dynamic    |     16384 |     0 |         0 |
| employees/t            | Barracuda   | Dynamic    |     16384 |     0 |         0 |
| employees/salaries     | Barracuda   | Dynamic    |     16384 |     0 |         0 |
| employees/employees    | Barracuda   | Dynamic    |     16384 |     0 |         0 |
| employees/dept_manager | Barracuda   | Dynamic    |     16384 |     0 |         0 |
| employees/dept_emp     | Barracuda   | Dynamic    |     16384 |     0 |         0 |
| employees/departments  | Barracuda   | Dynamic    |     16384 |     0 |         0 |
| employees/c            | Barracuda   | Dynamic    |     16384 |     0 |         0 |
+------------------------+-------------+------------+-----------+-------+-----------+
8 rows in set (0.05 sec)

IF()控制流函数用于处理压缩表。如果表被压缩,则使用ZIP_PAGE_SIZE而不是PAGE_SIZE计算索引大小。cluster_index_size和OTHER_INDEX_SIZE以字节为单位,它们除以1024*1024,就得到了以兆字节(MBs)为单位的索引长度。使用ROUND()函数将MB值四舍五入为0个小数空格。

发表评论

电子邮件地址不会被公开。