文档主页
MySQL 9.0 参考手册
相关文档 下载本手册

MySQL 9.0 参考手册  /  ...  /  InnoDB INFORMATION_SCHEMA 架构对象表

17.15.3 InnoDB INFORMATION_SCHEMA 架构对象表

您可以使用 InnoDB INFORMATION_SCHEMA 表提取有关 InnoDB 管理的架构对象的元数据。此信息来自数据字典。传统上,您将使用 第 17.17 节 “InnoDB 监视器” 中的技术来获取此类信息,设置 InnoDB 监视器并解析 SHOW ENGINE INNODB STATUS 语句的输出。InnoDB INFORMATION_SCHEMA 表接口允许您使用 SQL 查询这些数据。

InnoDB INFORMATION_SCHEMA 架构对象表包括此处列出的表

  • INNODB_DATAFILES

  • INNODB_TABLESTATS

  • INNODB_FOREIGN

  • INNODB_COLUMNS

  • INNODB_INDEXES

  • INNODB_FIELDS

  • INNODB_TABLESPACES

  • INNODB_TABLESPACES_BRIEF

  • INNODB_FOREIGN_COLS

  • INNODB_TABLES

表名表示提供的数据类型

InnoDB INFORMATION_SCHEMA 架构对象表可以通过 TABLE_IDINDEX_IDSPACE 等字段连接在一起,使您可以轻松检索要研究或监控的对象的所有可用数据。

有关每个表的列的信息,请参阅 InnoDB INFORMATION_SCHEMA 文档。

示例 17.2 InnoDB INFORMATION_SCHEMA 架构对象表

此示例使用具有单个索引 (i1) 的简单表 (t1) 来演示 InnoDB INFORMATION_SCHEMA 架构对象表中的元数据类型。

  1. 创建测试数据库和表 t1

    mysql> CREATE DATABASE test;
    
    mysql> USE test;
    
    mysql> CREATE TABLE t1 (
           col1 INT,
           col2 CHAR(10),
           col3 VARCHAR(10))
           ENGINE = InnoDB;
    
    mysql> CREATE INDEX i1 ON t1(col1);
  2. 创建表 t1 后,查询 INNODB_TABLES 以找到 test/t1 的元数据

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME='test/t1' \G
    *************************** 1. row ***************************
         TABLE_ID: 71
             NAME: test/t1
             FLAG: 1
           N_COLS: 6
            SPACE: 57
       ROW_FORMAT: Compact
    ZIP_PAGE_SIZE: 0
     INSTANT_COLS: 0

    t1TABLE_ID 为 71。 FLAG 字段提供有关表格式和存储特性的位级信息。共有六列,其中三列是由 InnoDB 创建的隐藏列(DB_ROW_IDDB_TRX_IDDB_ROLL_PTR)。表的 SPACE ID 为 57(值为 0 表示该表位于系统表空间中)。ROW_FORMAT 为 Compact。ZIP_PAGE_SIZE 仅适用于具有 Compressed 行格式的表。INSTANT_COLS 显示在使用带有 ALGORITHM=INSTANTALTER TABLE ... ADD COLUMN 添加第一个即时列之前的表中的列数。

  3. 使用 INNODB_TABLES 中的 TABLE_ID 信息,查询 INNODB_COLUMNS 表以获取有关表列的信息。

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_COLUMNS where TABLE_ID = 71\G
    *************************** 1. row ***************************
         TABLE_ID: 71
             NAME: col1
              POS: 0
            MTYPE: 6
           PRTYPE: 1027
              LEN: 4
      HAS_DEFAULT: 0
    DEFAULT_VALUE: NULL
    *************************** 2. row ***************************
         TABLE_ID: 71
             NAME: col2
              POS: 1
            MTYPE: 2
           PRTYPE: 524542
              LEN: 10
      HAS_DEFAULT: 0
    DEFAULT_VALUE: NULL
    *************************** 3. row ***************************
         TABLE_ID: 71
             NAME: col3
              POS: 2
            MTYPE: 1
           PRTYPE: 524303
              LEN: 10
      HAS_DEFAULT: 0
    DEFAULT_VALUE: NULL

    除了 TABLE_ID 和列 NAME 之外,INNODB_COLUMNS 还提供每个列的序号位置(POS)(从 0 开始并按顺序递增)、列 MTYPE 或“主类型”(6 = INT,2 = CHAR,1 = VARCHAR)、PRTYPE 或“精确类型”(一个二进制值,其位表示 MySQL 数据类型、字符集代码和可空性)以及列长度(LEN)。HAS_DEFAULTDEFAULT_VALUE 列仅适用于使用带有 ALGORITHM=INSTANTALTER TABLE ... ADD COLUMN 即时添加的列。

  4. 再次使用 INNODB_TABLES 中的 TABLE_ID 信息,查询 INNODB_INDEXES 以获取有关与表 t1 关联的索引的信息。

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_INDEXES WHERE TABLE_ID = 71 \G
    *************************** 1. row ***************************
           INDEX_ID: 111
               NAME: GEN_CLUST_INDEX
           TABLE_ID: 71
               TYPE: 1
           N_FIELDS: 0
            PAGE_NO: 3
              SPACE: 57
    MERGE_THRESHOLD: 50
    *************************** 2. row ***************************
           INDEX_ID: 112
               NAME: i1
           TABLE_ID: 71
               TYPE: 0
           N_FIELDS: 1
            PAGE_NO: 4
              SPACE: 57
    MERGE_THRESHOLD: 50

    INNODB_INDEXES 返回两个索引的数据。第一个索引是 GEN_CLUST_INDEX,它是 InnoDB 在表没有用户定义的聚簇索引时创建的聚簇索引。第二个索引(i1)是用户定义的辅助索引。

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

  5. 使用 INNODB_INDEXES 中的 INDEX_ID 信息,查询 INNODB_FIELDS 以获取有关索引 i1 字段的信息。

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FIELDS where INDEX_ID = 112 \G
    *************************** 1. row ***************************
    INDEX_ID: 112
        NAME: col1
         POS: 0

    INNODB_FIELDS 提供索引字段的 NAME 及其在索引中的序号位置。如果索引 (i1) 是在多个字段上定义的,则 INNODB_FIELDS 将提供每个索引字段的元数据。

  6. 使用 INNODB_TABLES 中的 SPACE 信息,查询 INNODB_TABLESPACES 表以获取有关表表空间的信息。

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE SPACE = 57 \G
    *************************** 1. row ***************************
              SPACE: 57
              NAME: test/t1
              FLAG: 16417
        ROW_FORMAT: Dynamic
         PAGE_SIZE: 16384
     ZIP_PAGE_SIZE: 0
        SPACE_TYPE: Single
     FS_BLOCK_SIZE: 4096
         FILE_SIZE: 114688
    ALLOCATED_SIZE: 98304
    AUTOEXTEND_SIZE: 0
    SERVER_VERSION: 8.4.0
     SPACE_VERSION: 1
        ENCRYPTION: N
             STATE: normal

    除了表空间的 SPACE ID 和关联表的 NAME 之外,INNODB_TABLESPACES 还提供表空间 FLAG 数据,它是有关表空间格式和存储特性的位级信息。还提供了表空间 ROW_FORMATPAGE_SIZE 以及其他几个表空间元数据项。

  7. 再次使用 INNODB_TABLES 中的 SPACE 信息,查询 INNODB_DATAFILES 以获取表空间数据文件的位置。

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_DATAFILES WHERE SPACE = 57 \G
    *************************** 1. row ***************************
    SPACE: 57
     PATH: ./test/t1.ibd

    数据文件位于 MySQL data 目录下的 test 目录中。如果使用 CREATE TABLE 语句的 DATA DIRECTORY 子句在 MySQL 数据目录之外的位置创建了 每个表一个文件 的表空间,则表空间 PATH 将是一个完全限定的目录路径。

  8. 最后一步,在表 t1TABLE_ID = 71)中插入一行并在 INNODB_TABLESTATS 表中查看数据。MySQL 优化器使用此表中的数据来计算在查询 InnoDB 表时使用哪个索引。此信息来自内存数据结构。

    mysql> INSERT INTO t1 VALUES(5, 'abc', 'def');
    Query OK, 1 row affected (0.06 sec)
    
    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESTATS where TABLE_ID = 71 \G
    *************************** 1. row ***************************
             TABLE_ID: 71
                 NAME: test/t1
    STATS_INITIALIZED: Initialized
             NUM_ROWS: 1
     CLUST_INDEX_SIZE: 1
     OTHER_INDEX_SIZE: 0
     MODIFIED_COUNTER: 1
              AUTOINC: 0
            REF_COUNT: 1

    STATS_INITIALIZED 字段指示是否已为该表收集统计信息。NUM_ROWS 是表中当前估计的行数。CLUST_INDEX_SIZEOTHER_INDEX_SIZE 字段分别报告存储表的聚簇索引和辅助索引的磁盘页数。MODIFIED_COUNTER 值显示由 DML 操作和外键级联操作修改的行数。AUTOINC 值是为任何基于自动递增的操作发出的下一个数字。表 t1 上没有定义自动递增列,因此该值为 0。REF_COUNT 值是一个计数器。当计数器达到 0 时,表示可以从表缓存中逐出表元数据。


示例 17.3 外键 INFORMATION_SCHEMA 架构对象表

INNODB_FOREIGNINNODB_FOREIGN_COLS 表提供有关外键关系的数据。此示例使用具有外键关系的父表和子表来演示在 INNODB_FOREIGNINNODB_FOREIGN_COLS 表中找到的数据。

  1. 使用父表和子表创建测试数据库

    mysql> CREATE DATABASE test;
    
    mysql> USE test;
    
    mysql> CREATE TABLE parent (id INT NOT NULL,
           PRIMARY KEY (id)) ENGINE=INNODB;
    
    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;
  2. 创建父表和子表后,查询 INNODB_FOREIGN 并找到 test/childtest/parent 外键关系的外键数据

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FOREIGN \G
    *************************** 1. row ***************************
          ID: test/fk1
    FOR_NAME: test/child
    REF_NAME: test/parent
      N_COLS: 1
        TYPE: 1

    元数据包括外键 IDfk1),它是为在子表上定义的 CONSTRAINT 命名的。FOR_NAME 是定义外键的子表的名称。REF_NAME 是父表(“被引用” 表)的名称。N_COLS 是外键索引中的列数。TYPE 是一个数值,表示提供有关外键列的附加信息的位标志。在这种情况下,TYPE 值为 1,这表明已为外键指定了 ON DELETE CASCADE 选项。有关 TYPE 值的更多信息,请参见 INNODB_FOREIGN 表定义。

  3. 使用外键 ID,查询 INNODB_FOREIGN_COLS 以查看有关外键列的数据。

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FOREIGN_COLS WHERE ID = 'test/fk1' \G
    *************************** 1. row ***************************
              ID: test/fk1
    FOR_COL_NAME: parent_id
    REF_COL_NAME: id
             POS: 0

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


示例 17.4 连接 InnoDB INFORMATION_SCHEMA 架构对象表

此示例演示了如何连接三个 InnoDB INFORMATION_SCHEMA 架构对象表(INNODB_TABLESINNODB_TABLESPACESINNODB_TABLESTATS),以收集有关 employees 示例数据库中表的 文件格式、行格式、页面大小和索引大小的信息。

以下表别名用于缩短查询字符串

使用 IF() 控制流函数来考虑压缩表。如果表已压缩,则使用 ZIP_PAGE_SIZE 而不是 PAGE_SIZE 计算索引大小。以字节为单位报告的 CLUST_INDEX_SIZEOTHER_INDEX_SIZE 除以 1024*1024 以提供以兆字节 (MB) 为单位的索引大小。使用 ROUND() 函数将 MB 值舍入到零个小数位。

mysql> SELECT a.NAME, 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_TABLES a
       INNER JOIN INFORMATION_SCHEMA.INNODB_TABLESPACES b on a.NAME = b.NAME
       INNER JOIN INFORMATION_SCHEMA.INNODB_TABLESTATS c on b.NAME = c.NAME
       WHERE a.NAME LIKE 'employees/%'
       ORDER BY a.NAME DESC;
+------------------------+------------+-----------+-------+-----------+
| NAME                   | ROW_FORMAT | page_size | pk_mb | secidx_mb |
+------------------------+------------+-----------+-------+-----------+
| employees/titles       | Dynamic    |     16384 |    20 |        11 |
| employees/salaries     | Dynamic    |     16384 |    93 |        34 |
| employees/employees    | Dynamic    |     16384 |    15 |         0 |
| employees/dept_manager | Dynamic    |     16384 |     0 |         0 |
| employees/dept_emp     | Dynamic    |     16384 |    12 |        10 |
| employees/departments  | Dynamic    |     16384 |     0 |         0 |
+------------------------+------------+-----------+-------+-----------+