MySQL 8.0数据字典的重大变化与实战场景教学
作者:detayun
前言
很多开发天天写 SELECT、建表、改索引,却很少接触 MySQL 的数据字典。简单说:数据字典就是 MySQL 存放自身元数据的一套系统表,记录库、表、字段、索引、约束、权限、存储引擎信息。
我们平时执行 SHOW TABLES、DESC table_name,底层本质就是查询数据字典。
MySQL5.7 和 8.0 数据字典有很大区别:5.7 元数据分散在 information_schema,8.0 重构,把核心数据字典迁移到 mysql 库下的内部表,information_schema 变成视图。
版本说明:本文覆盖 MySQL5.7 / 8.0,InnoDB引擎。
一、三个核心系统库区分
很多人混淆这三个库,先分清:
- information_schema:只读视图,对外暴露元数据,最常用。查询表、字段、索引、约束基本都查这里。
- mysql:系统核心库,存储用户账号、权限、系统配置。MySQL8.0 核心数据字典底层表放在这里,不建议直接修改底层字典表。
- performance_schema:性能监控、等待事件、SQL执行监控,和数据字典无关。
重点:不要手动UPDATE/DELETE修改数据字典底层表,极易直接损坏数据库,只能通过DDL语句(CREATE/ALTER/DROP)修改。
二、information_schema 常用表实战
1. SCHEMATA:查询所有数据库
SELECT schema_name, default_character_set_name, default_collation_name FROM information_schema.SCHEMATA;
等价于 SHOW DATABASES;
2. TABLES:表信息(库、表名、引擎、行数、表大小、注释)
日常审计、统计库里面所有表、判断存储引擎、查询表注释,高频使用。
SELECT TABLE_SCHEMA AS 数据库名, TABLE_NAME AS 表名, ENGINE AS 存储引擎, TABLE_ROWS AS 预估行数, DATA_LENGTH AS 数据字节, INDEX_LENGTH AS 索引字节, TABLE_COMMENT AS 表注释 FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'test_db';
注意:TABLE_ROWS 是InnoDB预估值,不是精确行数,不能当作真实记录数。
3. COLUMNS:字段详情(字段名、类型、长度、是否为空、默认值、注释)
替代 DESC table_name,批量导出表结构、文档生成非常好用。
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='test_db' AND TABLE_NAME='shop';
4. STATISTICS:索引信息(主键、联合索引、索引字段、唯一索引)
批量查询所有索引、排查冗余索引、查看联合索引顺序。
SELECT TABLE_NAME, INDEX_NAME, NON_UNIQUE, SEQ_IN_INDEX, COLUMN_NAME, INDEX_COMMENT FROM information_schema.STATISTICS WHERE TABLE_SCHEMA='test_db' AND TABLE_NAME='shop';
NON_UNIQUE=0:唯一索引 / 主键SEQ_IN_INDEX:联合索引内字段顺序,就是最左前缀的顺序
5. KEY_COLUMN_USAGE:主键、外键约束
查询主键字段、外键关联关系,做数据库结构审计。
SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA='test_db';
6. PARTITIONS:分区表信息
查询分区表的分区定义、分区边界。
SELECT * FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA='test_db';
三、MySQL8.0 数据字典的重大变化
MySQL 5.7:
- 元数据全部存在
information_schema,是实时从各个系统文件读取,查询慢; - 没有统一数据字典,frm文件存储表定义,表多的时候打开表开销大。
MySQL8.0 重构事务型数据字典:
- 表定义不再存在frm文件,全部存入mysql库下InnoDB内部字典表;
- 数据字典支持事务,DDL崩溃更安全;
information_schema不再存储原始数据,只是视图,查询时从底层字典表读取;- 数据字典表默认隐藏,不能直接访问,只能通过information_schema视图读取。
简单理解:5.7是文件存表结构;8.0把表结构放进数据库内部InnoDB表,更稳定。
四、数据字典能做哪些实战场景
场景1:批量生成建表文档
业务数据库表很多,手动写文档麻烦,直接查询 COLUMNS,导出结果生成数据库设计文档。
场景2:批量查找没有主键的表
数据库规范审计,检查漏建主键的表(InnoDB强烈建议所有表要有主键)
SELECT
t.TABLE_SCHEMA,
t.TABLE_NAME
FROM information_schema.TABLES t
LEFT JOIN information_schema.KEY_COLUMN_USAGE k
ON t.TABLE_SCHEMA = k.TABLE_SCHEMA AND t.TABLE_NAME = k.TABLE_NAME AND k.CONSTRAINT_TYPE='PRIMARY KEY'
WHERE t.TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema')
AND k.CONSTRAINT_NAME IS NULL;
场景3:查找冗余索引
通过STATISTICS分析,找出可以被联合索引覆盖的冗余单字段索引,清理索引减少写入压力。
场景4:批量修改字段、批量查询注释
批量检索所有表里面某个字段,例如查找整个库里所有表包含phone字段:
SELECT TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME FROM information_schema.COLUMNS WHERE COLUMN_NAME='phone' AND TABLE_SCHEMA='test_db';
五、常见坑点
TABLE_ROWS是估算值:InnoDB为了性能,不会实时统计精确行数,TABLE_ROWS只是采样估算,不能用来统计真实记录数。
information_schema查询大库会慢:表数量非常多的时候,查询information_schema会扫描大量元数据,生产高峰期不要频繁执行。
不要直接修改mysql底层字典表:8.0底层数据字典表是内部表,强行修改会导致库损坏,无法启动。只能用DDL。
字符集、排序规则注意区分;SCHEMATA 存库级字符集,COLUMNS存字段级字符集,表、字段可以和库不一样。
视图定义在VIEWS表:information_schema.VIEWS 可以查询视图的创建语句。
六、SHOW命令 和 数据字典关系
SHOW 本质是对information_schema的封装:
SHOW TABLES→ 查询 SCHEMATA + TABLESDESC / DESCRIBE table→ 查询 COLUMNSSHOW INDEX FROM table→ 查询 STATISTICSSHOW CREATE TABLE table→ 读取字典中表定义
如果需要批量处理、导出、审计,直接查询information_schema,比一条条show方便得多。
七、安全与权限
普通账号默认只能看到自己有权限访问的库和表。
如果账号没有访问某个表的权限,在information_schema里也看不到该表的元数据,防止泄露库结构。
小结
MySQL数据字典就是数据库自己记录库、表、字段、索引的元数据仓库。
日常开发中,SHOW命令适合临时查看;批量审计、导出表结构、查找冗余索引、数据库规范检查,优先查询information_schema。
MySQL8.0重构后的事务型数据字典,解决了老版本frm文件的稳定性问题,但我们开发使用层面,依然主要通过information_schema视图来访问元数据。
到此这篇关于MySQL 8.0数据字典的重大变化与实战场景教学的文章就介绍到这了,更多相关MySQL数据字典内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
