在日常数据库运维工作中,我们经常需要监控MySQL数据库的存储使用情况。特别是当服务器磁盘空间告警时,快速定位哪些业务库占用了大量空间,以及这些库中哪些表是"空间大户"就显得尤为重要。通过命令行直接查询库表大小,比登录phpMyAdmin等图形工具更高效,尤其适合自动化监控场景。
上周我们生产环境就遇到了一次磁盘空间不足的紧急情况。当时通过这套方法,5分钟内就锁定了某个日志表异常增长的问题,及时清理后避免了服务中断。下面就把这个实用技巧完整分享给大家。
基础命令:
sql复制SELECT
table_schema AS '数据库',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS '大小(MB)'
FROM
information_schema.tables
GROUP BY
table_schema
ORDER BY
SUM(data_length + index_length) DESC;
关键点说明:
data_length:数据部分占用空间index_length:索引部分占用空间注意:information_schema是MySQL自带的元数据库,存储了所有库表的元信息
以查看名为order_db的库为例:
sql复制SELECT
table_name AS '表名',
ROUND(data_length/1024/1024, 2) AS '数据大小(MB)',
ROUND(index_length/1024/1024, 2) AS '索引大小(MB)',
ROUND((data_length + index_length)/1024/1024, 2) AS '总大小(MB)',
table_rows AS '行数'
FROM
information_schema.tables
WHERE
table_schema = 'order_db'
ORDER BY
(data_length + index_length) DESC;
将查询结果输出到文件:
bash复制mysql -uroot -p -e "SELECT table_schema, ROUND(SUM(data_length + index_length)/1024/1024,2) FROM information_schema.tables GROUP BY table_schema;" > db_size_report.txt
sql复制SELECT
table_schema AS '数据库',
table_name AS '表名',
ROUND((data_length + index_length)/1024/1024, 2) AS '大小(MB)'
FROM
information_schema.tables
WHERE
ROUND((data_length + index_length)/1024/1024, 2) > 1024
ORDER BY
(data_length + index_length) DESC;
高碎片化表会影响性能:
sql复制SELECT
table_name AS '表名',
data_free AS '碎片空间(字节)',
ROUND(data_free/(data_length + index_length)*100, 2) AS '碎片率(%)'
FROM
information_schema.tables
WHERE
table_schema = 'order_db'
AND data_free > 0
ORDER BY
data_free DESC;
常见报错:"SELECT command denied to user"
SELECT权限sql复制GRANT SELECT ON information_schema.* TO 'monitor_user'@'%';
table_rows是估算值,MyISAM准确但InnoDB可能有偏差COUNT(*),但大表性能消耗大常用换算公式:
虽然本文聚焦命令行,但可以结合其他工具:
可能原因:
检查:
解决方案:
这套方法在我们生产环境已经稳定运行3年,帮助处理了数十次存储告急情况。特别是当多个业务团队共用数据库时,能快速定位责任方,避免互相推诿。建议DBA同学都将其加入日常巡检清单。