information_schema 是 MySQL 自带的只读元数据库,存储其他数据库的结构信息而非业务数据,不能创建表或删除,因其由服务端动态生成而非真实磁盘数据库。

information_schema 是什么,为什么不能当普通数据库用
information_schema 是 MySQL 自带的“元数据库”,它不存业务数据,只存其他数据库的结构信息:表名、列类型、索引定义、权限设置等。它本质是只读视图集合,底层由 MySQL 服务端动态生成,不是磁盘上的真实数据库。
常见错误现象:CREATE TABLE information_schema.my_log (...) 报错 ERROR 1044 (42000): Access denied for user;或者试图 DROP DATABASE information_schema 被拒绝——这不是权限问题,是设计限制。
使用场景有限但关键:排查慢查询时查 information_schema.PROCESSLIST(注意 8.0+ 已推荐用 performance_schema 替代);查某张表用了多少索引就看 STATISTICS 表;想确认字段是否为 NULL 就翻 COLUMNS 表。
查表结构最常用三张表怎么选
COLUMNS、TABLES、STATISTICS 是日常查结构最常碰的三张表,但用途差异明显:
-
COLUMNS:查字段级细节,比如IS_NULLABLE、DATA_TYPE、COLUMN_DEFAULT。适合写自动化脚本判断字段是否允许为空。 -
TABLES:查库/表基础信息,TABLE_ROWS看的是估算值(MyISAM 准,InnoDB 不准),ENGINE和CREATE_TIME倒是可靠。 -
STATISTICS:查索引字段顺序和是否唯一,SEQ_IN_INDEX = 1表示是联合索引的第一列,NON_UNIQUE = 0才是唯一索引。
性能影响:这些查询本身不锁表,但高并发下频繁查 information_schema 可能引发元数据锁争用,尤其在表数量极多(>10k)时响应变慢。建议加 WHERE TABLE_SCHEMA = 'your_db' 缩小范围。
MySQL 5.7 和 8.0 的 information_schema 差异点
升级后容易踩坑的地方集中在两处:
-
PROCESSLIST表在 8.0 中默认不显示其他用户会话,需开启show_processlist权限或用performance_schema.threads替代。 -
INNODB_SYS_*系列表(如INNODB_SYS_TABLES)在 8.0 中字段名有调整,比如NAME改成TABLE_NAME,旧脚本直接报Unknown column。 -
COLLATION_NAME在COLUMNS表中,5.7 返回空字符串表示默认排序规则,8.0 统一返回实际值(如utf8mb4_0900_ai_ci),依赖空值判断的代码会失效。
兼容性建议:跨版本迁移脚本时,优先用 SHOW CREATE TABLE 或 DESCRIBE 做兜底,别全靠 information_schema 字段硬编码。
哪些查询看起来合理但实际低效甚至危险
看似简单的一条 SELECT,可能拖慢整个实例:
-
SELECT * FROM information_schema.COLUMNS—— 全库所有字段拉一遍,上万张表时内存暴涨,可能触发 OOM。 -
SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql','sys','information_schema')—— 每次执行都遍历所有库的表定义,比SHOW DATABASES+ 单库SHOW TABLES慢数倍。 - 在存储过程中循环查
information_schema做条件判断(比如“如果某列存在则更新”),每次调用都触发元数据刷新,极易成为性能瓶颈。
真正安全的做法是:缓存结果(比如应用层定期拉一次 COLUMNS 存 Redis),或改用 SHOW COLUMNS FROM tbl_name 这类轻量命令——它走的是相同元数据路径,但开销可控。
复杂点在于:information_schema 的数据不是实时快照,而是按需生成。你查到的 TABLE_ROWS 可能是几秒前的,而 INDEX_LENGTH 又可能滞后于 Buffer Pool 刷盘。信它结构,别信它数值。










