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_表信息
INNODB_ TABLES
-
INNODB_ 列信息
INNODB_ COLUMNS
-
INNODB_ 索引信息
INNODB_ INDEXES
-
INNODB_ 字段信息
INNODB_ FIELDS
-
INNODB_ 表状态信息
INNODB_ TABLESTATS
-
INNODB_ 数据文件信息
INNODB_ DATAFILES
-
INNODB_TABLESPACES 提供了关于
InnoDB
文件-per-表、通用和undo 表空间的元数据。 -
INNODB_TABLESPACES_BRIEF 提供了关于
InnoDB
表空间的元数据子集。 -
INNODB_FOREIGN 提供了关于在
InnoDB
表上定义的外键元数据。 -
INNODB_FOREIGN_COLS 提供了关于在
InnoDB
表上定义的外键列元数据。
InnoDB
INFORMATION_SCHEMA
schema 对象表可以通过字段如 TABLE_ID
、INDEX_ID
和 SPACE
进行连接,从而允许您轻松地检索要研究或监控的对象所有可用数据。
请参阅 InnoDB
INFORMATION_SCHEMA 文档,以获取每个表的列信息。
示例 17.2 InnoDB INFORMATION_ SCHEMA Schema 对象表
这个示例使用了一个简单的表(t1
),带有一个单独的索引(i1
),来演示InnoDB
INFORMATION_SCHEMA
schema 对象表中的元数据类型。
-
创建一个测试数据库和表
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);
-
在创建表
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
表
t1
具有一个TABLE_ ID
为71。FLAG
字段提供了关于表格式和存储特征的位级信息。有六个列,其中三个是由InnoDB
创建的隐藏列(DB_ROW_ID
、DB_TRX_ID
和DB_ROLL_PTR
)。表的SPACE
ID为57(一个值为0将表示该表位于系统表空间)。ROW_FORMAT
是紧凑格式。ZIP_PAGE_SIZE
仅适用于具有压缩行格式的表。INSTANT_COLS
显示了在使用ALTER TABLE ... ADD COLUMN
语句添加第一个瞬时列时表中的列数,该语句中使用了ALGORITHM=INSTANT
。 -
使用
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
还提供每列的顺序位置(从0开始,顺序递增),列MTYPE
或“主类型”(6=INT,2=CHAR,1=VARCHAR),列PRTYPE
或“精确类型”(一个二进制值,其中包含MySQL数据类型、字符集代码和可空性),和列长度LEN
。只有使用ALTER TABLE ... ADD COLUMN
语句添加的列,才会应用于HAS_DEFAULT
和DEFAULT_VALUE
列。 -
使用
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
在实例中唯一,表明该索引所属的表。索引类型TYPE
值表示索引类型(1 = Clustered Index,0 = Secondary index)。N_FILEDS
值是索引中的字段数量。PAGE_NO
是索引B-树的根页号,SPACE
是索引所在表空间的ID。非零值表示索引不在系统表空间中。MERGE_THRESHOLD
定义了索引页面中的数据量百分比阈值。如果索引页面中的数据量低于该值(默认为50%)当删除或更新操作缩短行时,InnoDB
将尝试合并索引页面与邻近索引页面。 -
使用
INNODB_INDEXES
中的INDEX_ID
信息,查询INNODB_FIELDS
以获取索引1的字段信息。mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FIELDS where INDEX_ID = 112 \G *************************** 1. row *************************** INDEX_ID: 112 NAME: col1 POS: 0
INNODB_FIELDS
提供了索引字段的NAME
和在索引中 ordinal 位置。如果该索引(i1)已定义为多个字段,INNODB_FIELDS
将为每个索引字段提供元数据。 -
使用
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_FORMAT
、PAGE_SIZE
和其他多个表空间元数据项。 -
使用
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
子目录。如果使用file-per-table表空间在 MySQL 数据目录外创建了一个文件夹,使用CREATE TABLE
语句的DATA DIRECTORY
子句,那么表空间的PATH
将是一个完全合格的目录路径。 -
最后一步是向表
t1
(TABLE_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_SIZE
和OTHER_INDEX__SIZE
字段报告存储该表聚簇索引和次要索引的磁盘页面数量,分别。MODIFIED_COUNTER
值显示由DML操作和外键级联操作修改的行数。AUTOINC
值是下一个用于自增操作的数字。在表t1
中没有定义自增列,所以该值为0。REF_ COUNT
值是一个计数器。当计数器达到0时,表示表元数据可以从表缓存中删除。
示例17.3 外键INFORMATION_SCHEMA对象表
表INNODB_FOREIGN
和INNODB_FOREIGN_COLS
提供关于外键关系的数据。该示例使用父表和子表之间的外键关系来演示INNODB_FOREIGN
和INNODB_FOREIGN_COLS
表中的数据。
-
创建测试数据库,包括父表和子表:
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;
-
在创建父表和子表后,查询
INNODB_FOREIGN
,找到test/child
和test/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
元数据包括外键
ID
(fk1
),该名称来自于子表上定义的约束。FOR_NAME
是子表名称,其中定义了外键。REF_NAME
是父表名称(被引用表)。N_COLS
是外键索引中的列数。TYPE
是一个数字值,表示位标志,提供关于外键列的额外信息。在这个例子中,TYPE
值为1,表示指定了外键的“ON DELETE CASCADE”选项。请查看INNODB_FOREIGN
表定义,以获取更多关于TYPE
值的信息。 -
使用外键
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 Schema Object Tables Joining
这个示例演示了将三个InnoDB
INFORMATION_SCHEMA
schema object tables (INNODB_TABLESPACES
, INNODB_TABLESTATS
)连接起来,以获取employees示例数据库中的表的文件格式、行格式、页面大小和索引大小信息。
以下是用于简化查询字符串的表别名:
使用IF()
控制流函数来处理压缩表。如果一个表是压缩的,索引大小将使用ZIP_PAGE_SIZE
而不是PAGE_SIZE
进行计算。CLUST_INDEX_SIZE
和OTHER_INDEX_SIZE
,以字节为单位报告的值,将被除以1024*1024
以提供索引大小(MB)。MB值使用ROUND()
函数进行四舍五入到小数点后零位。
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 |
+------------------------+------------+-----------+-------+-----------+