查所有数据库大小必须用information_schema.tables,因其是唯一能批量获取库表容量元数据的只读视图集合,字段如data_length、index_length源自存储引擎统计快照,不扫描物理文件;需group by table_schema并结合data_length+index_length估算逻辑大小,但真实磁盘占用须用du -sh验证。

查所有数据库大小必须用 information_schema.TABLES
直接连上 MySQL 后,information_schema 是唯一能批量获取库表容量元数据的地方。它不是普通数据库,而是一个只读视图集合,所有字段(如 DATA_LENGTH、INDEX_LENGTH)都来自存储引擎的统计快照,不涉及实际文件扫描。
常见错误是误以为 SELECT SUM(data_length) FROM tables 就能准确反映磁盘占用——其实它只反映“逻辑数据量”,不含碎片、未回收空间、redo log 或 binlog 占用。真实磁盘大小需结合 du -sh 查看数据目录。
-
table_schema字段对应数据库名,但要注意:系统库(如mysql、performance_schema)也包含在内,若只想看业务库,得加WHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys') -
DATA_LENGTH + INDEX_LENGTH是常用组合,但对 InnoDB 表来说,这俩值是采样估算的,尤其大表刚删完大量数据后,DATA_LENGTH可能远小于实际磁盘释放量 - 单位换算容易出错:除以
1024*1024得 MB,除以1024*1024*1024得 GB;用ROUND()比TRUNCATE()更稳妥,避免小数截断导致 0.99 MB 显示成 0 MB
SELECT 语句里 GROUP BY table_schema 是核心逻辑
不加 GROUP BY 会把所有库的数据全加总,失去“每个库多大”的意义。典型写法是:
SELECT table_schema AS `database`, ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS `size_mb`, ROUND(SUM(data_free) / 1024 / 1024, 2) AS `free_mb` FROM information_schema.TABLES GROUP BY table_schema ORDER BY size_mb DESC;
这里 data_free 值对 InnoDB 表仅表示“当前可被 purge 回收的空间”,不是“还能插入多少数据”,别把它当剩余容量用。
- 如果某库结果为空(
NULL),大概率是该库下没有 InnoDB 或 MyISAM 表,比如只有 VIEW 或空库 - MyISAM 表的
DATA_LENGTH和INDEX_LENGTH更接近实时值;InnoDB 表依赖innodb_stats_persistent设置,默认开启,统计更新有延迟 - 执行该查询需要
PROCESS权限或至少对information_schema的 SELECT 权限;某些云厂商(如阿里云 RDS)会限制访问information_schema.TABLES的行数,超限时返回不完整结果
为什么不能只看 DATA_LENGTH?
DATA_LENGTH 只是表数据页的逻辑大小,不包括索引、回滚段、undo log、change buffer 等。单独看它,等于只看了冰山一角。
例如一张 500MB 的 InnoDB 表,DATA_LENGTH 可能显示 480MB,INDEX_LENGTH 显示 120MB,但磁盘上 .ibd 文件实际是 650MB——多出来的 50MB 就是碎片和预留空间。
- 真正反映磁盘占用的是
DATA_LENGTH + INDEX_LENGTH + DATA_FREE的总和,但它仍是估算值;精确值得用操作系统命令:du -sh /var/lib/mysql/your_db_name/*.ibd 2>/dev/null | tail -n1 - 如果发现某库的
size_mb远大于磁盘du结果,可能是该库含大量 MyISAM 表(.MYD/.MYI文件未被计入TABLES统计) -
INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES提供FILE_SIZE字段,它是未压缩的原始文件大小,但仅对独立表空间(innodb_file_per_table=ON)有效,且需额外权限
执行慢或查不到数据?先确认权限和引擎状态
查 information_schema.TABLES 慢,通常不是 SQL 本身问题,而是底层统计信息陈旧或表太多触发全扫描。
- 运行
SHOW VARIABLES LIKE 'innodb_stats_persistent';,若为OFF,说明统计靠临时采样,DATA_LENGTH波动大;建议设为ON并定期ANALYZE TABLE - 用
SELECT COUNT(*) FROM information_schema.TABLES WHERE table_schema = 'your_db';看该库有多少张表,超过 5000 张时,查询可能明显变慢 - 某些低版本 MySQL(如 5.6)中,
information_schema.TABLES查询会锁表或阻塞 DDL,升级到 5.7+ 可缓解 - 如果结果里
size_mb全是 0,检查是否用了BLACKHOLE或MEMORY引擎——它们不持久化数据,DATA_LENGTH恒为 0
真正要落地评估扩容或归档,不能只信 information_schema 里的数字;它适合快速摸底和趋势对比,而不是精确计量。











