MySQL 磁盘 80% 告警,碎片 52G,我差点 TRUNCATE 掉正在写入的业务表

【信息科学与工程学】计算机科学与自动化——第三百零四篇 高性能系统开发指南01 高并发:限流、熔断、降级高性能:红包拆分、多级缓存、大Key/热Key拆分、Pipeline、线程池、RocketMQ零丢失、幂等、分布式锁、集群缩容、分批入库海量数据处理:日志分表分片、跨表查询、冷热分层、大数据引擎服务器选型系统安全:网关安全、服务器安全、云存储安全、风控、监控、测试数据一致性:缓存与数据库一致性、大厂方案、蓝绿回滚、流量一致性、流程一致性项目与团队管理:流程问题、管理问题(风险、成本、人员、文档、培训)稳定性建设:上线三板斧、线上五步闭环、混沌工程、容量规划。 阅读详情

大家好,我是老张。

连着写了三天博客安全系列,今天换个话题——生产踩坑。

上周写个人博客后台写嗨了,差点在生产环境捅个大篓子。

⚠️ 声明:本文基于真实生产环境排查案例编写,已对 IP 地址、实例名、库名/表名、密码等敏感信息做脱敏处理,命令可直接复制执行。

"磁盘 80% 告警,碎片 52G,TRUNCATE 一下不就完了?"

我相信绝大多数运维人的第一反应都是这个。说实话,我当时也这么想的。

直到我多做了一个操作——查了一下数据的最晚写入时间。

然后冷汗都下来了。


📊 告警来了

某天下午,监控弹出一条告警:Meta MySQL 磁盘使用率超过 80%。

进云平台控制台一看,实例规格 4C16G,磁盘 150GB 本地 SSD,用了 120G。主节点 80.07%,备节点 79.72%,同步正常。

先看磁盘分拆:数据 119.6G + Binlog 509M + 日志 5M。

Binlog 才 500M——不是 Binlog 堆积,数据文件有问题。


🔍 排查:差额到底在哪?

SSH 到管理节点,进 Pod 直连 MySQL:

# SSH 到管理节点
ssh <管理节点IP>

# 进 Pod 直连 MySQL
kubectl exec -it <pod名> -n <namespace> -- mysql -uroot -p

先 SQL 统计各库大小:

SELECT table_schema AS '库名',
       ROUND(SUM(data_length + index_length) / 1024/1024/1024, 2) AS 'SQL统计(GB)'
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
GROUP BY table_schema ORDER BY 2 DESC;
库SQL 统计
库A16.8G
库B8.3G
库C5.1G
库D5.1G

所有库加起来才 ~44G。但磁盘用了 120G——差了 76G。

再用磁盘实际占用对比 SQL 统计,定位差额:

# 进 Pod 的 mysql 容器,直接 du 各库目录
kubectl exec -it <pod名> -n <namespace> -c mysql -- bash -c \
  "du -sh /var/lib/mysql/*/ 2>/dev/null | sort -rh | head -10"
库目录磁盘实际SQL 统计碎片
库B60G8.3G51.7G 🔴
库A23G16.8G6.2G
库C7.6G5.1G2.5G
库D6.8G5.1G1.7G

一个库吃掉了 52G 碎片。

精确量化:data_free 排名

要找碎片最大的表,最快的方式是看各表的 .ibd 文件实际大小,再跟 SQL 统计对比:

# 进 Pod,查目标库下所有 .ibd 文件大小
kubectl exec -it <pod名> -n <namespace> -c mysql -- bash -c \
  "du -sh /var/lib/mysql/<库名>/*.ibd 2>/dev/null | sort -rh | head -15"

结果跟 du 数据吻合——8 张表的 .ibd 文件远大于 SQL 统计值。下一步用 data_free 精确量化。

DBA 要求用 information_schema.TABLES 的 data_free 字段——这个字段统计的是 InnoDB 内部已分配但未使用的空间,比 du 更准确:

SELECT
  CONCAT(table_schema, '.', table_name) table_name,
  ROUND((data_length + index_length) / 1024/1024, 2) AS '数据大小(M)',
  ROUND(data_free / 1024/1024, 2) AS '碎片(M)',
  (100*(data_free/(data_length+index_length+data_free))) AS '浪费比例%'
FROM information_schema.TABLES
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
ORDER BY data_free DESC LIMIT 8;

结果触目惊心:

表实际数据碎片总占用浪费比例
表11.4G9.2G10.6G86.3%
表2666M7.6G8.3G92.0%
表3152M6.6G6.8G97.8%
表41.1G5.2G6.4G81.7%
表5103M4.3G4.4G97.7%
表669M4.0G4.1G98.3%
表783M3.2G3.3G97.5%
表82.6G1.9G4.6G41.0%

8 张表合计碎片约 46G,大部分浪费比例 80%+。其中表 3 最夸张——实际数据只有 152M,碎片却有 6.6G,浪费 97.8%。

看到这个数据,我脑子里的第一反应不是"这表还在用吗?"——而是"这表居然能有这么多碎片?"

98% 的浪费率,大脑会直接下结论:这是张废弃表,没人管了。

更何况,业务方上周刚跟我说过"库B那几张历史表没用了,有空清一下"。

到这一步,直觉告诉我:TRUNCATE 掉就完事了。


⚠️ 转折:多做了一个操作

正准备提单 TRUNCATE,突然想到一个问题——这表还在用吗?

先看表结构,找时间字段:

SHOW FULL COLUMNS FROM 库B.表1;

常见时间字段叫 created_time、gmt_create、create_time,找到后查数据时间范围:

SELECT
  MIN(created_time) AS 最早创建,
  MAX(created_time) AS 最晚创建,
  COUNT(*) AS 总行数
FROM 库B.表1;

结果:

最早创建: 2026-07-25 23:15:02
最晚创建: 2026-08-04 11:00:31   ← 就是现在!
总行数:   202,257

最晚创建时间就是查询时刻——这张表是活的,实时高频率写入中。20 万行记录仅 10 天数据,9.2G 碎片来自频繁 INSERT/UPDATE/DELETE,InnoDB 来不及回收。

如果刚才直接 TRUNCATE,几 万行业务数据就没了。

😱 冷汗都下来了。


💡 决策矩阵

面对碎片表,判断能不能 TRUNCATE 的关键不是碎片大小,而是数据时间范围:

时间特征判断方案
最早 > 6 个月前,最晚也是 6 个月前冷数据TRUNCATE(确认业务已停)
最早 < 1 个月前,最晚 = 此刻活跃写入OPTIMIZE,不能 TRUNCATE
时间跨度短 + 行数多高频写入碎片低峰期 OPTIMIZE

🛠️ OPTIMIZE 执行:比预估快 20 倍

方案确定:逐表 OPTIMIZE TABLE,变更窗口定在下午 6 点。

-- 逐表执行,每张跑完再跑下一张
OPTIMIZE TABLE 库B.表1;
OPTIMIZE TABLE 库B.表2;
OPTIMIZE TABLE 库B.表3;
OPTIMIZE TABLE 库B.表4;
OPTIMIZE TABLE 库B.表5;
OPTIMIZE TABLE 库B.表6;
OPTIMIZE TABLE 库B.表7;
OPTIMIZE TABLE 库B.表8;

预估:表 1 有 10.6G 总占用,按经验得跑十几分钟。8 张表下来至少 1 小时。

实际执行:

#表碎片实际耗时结果
1表81.9G1m39s✅
2表73.2G0.6s✅
3表64.0G2.9s✅
4表54.3G3.4s✅
5表45.2G6.4s✅
6表36.6G5.3s✅
7表27.6G15.6s✅
8表19.2G9.7s✅
合计~46G~3 分钟

8 张表跑完,总共不到 3 分钟。

为什么这么快?因为表虽然总占用 8-10G,但 86-98% 是碎片。OPTIMIZE 只拷贝有效数据——10G 的表实际数据只有 1.4G,搬这点东西当然快。


🎉 最终效果

磁盘使用率:80% → 53%,回收约 40G。

节点磁盘数据Binlog同步
主52.93%78.8G583M0ms
备52.92%78.7G560M1s

❓ 读者可能会问:碎片这么大了为什么不清?

很简单:之前没人知道。

  • 业务方:表还在正常写入,不知道有碎片问题
  • 开发:只管用业务逻辑,不会定期查 data_free
  • DBA:管几百个实例,顾不上这种"还没爆雷"的碎片
  • 运维:只看磁盘使用率,80% 告警才拉群

这就是运维的日常——问题不到炸出来的那一刻,没人会主动关注。

如果今天不是我多查了一步 MAX(created_time),这张表就没了。


💡 老张的经验总结

✅ 做对了什么

  1. 先排除 Binlog——控制台分拆一看 500M,直接跳过不必要的排查
  2. du vs SQL 双对比——磁盘 60G、SQL 8G,差额就是碎片,定位精准
  3. data_free 精确量化——比 du 估算更准,而且是 DBA 认可的标准指标
  4. 数据活跃度验证——这是整个排查中最关键的一步。碎片再大也不能无脑 TRUNCATE
  5. OPTIMIZE 比预估快——碎片率越高跑得越快,因为只搬有效数据

⚠️ 如果再遇到这种事

  1. 先查时间范围,再做决策——不管你多确定这表没用了,不管业务方跟你说过多少次"这表可以清",跑一条 SELECT MIN/MAX 只要 0.1 秒。别人说的"没用",跟数据库里的"真没用",中间隔了 几万行数据。
  2. 定时统计 data_free——可以加到巡检脚本里,碎片率 > 50% 就告警,别等 80% 了再处理
  3. 碎片率越高的表,OPTIMIZE 越快——这个反直觉的事实,记下来
  4. "业务方说没用"不算数,"最后一条写入是半年前"才算数——口头承诺不可信,数据库里的时间戳才是铁证

🔧 碎片排查命令速查

-- 1. 查看各库碎片 Top
SELECT
  table_schema AS '库',
  ROUND(SUM(data_free) / 1024/1024/1024, 2) AS '碎片(GB)'
FROM information_schema.TABLES
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
GROUP BY table_schema ORDER BY 2 DESC;

-- 2. 查看某库表碎片排名(含浪费比例)
SELECT
  table_name AS '表名',
  ROUND((data_length + index_length) / 1024/1024, 2) AS '数据(M)',
  ROUND(data_free / 1024/1024, 2) AS '碎片(M)',
  ROUND(100 * data_free / (data_length + index_length + data_free), 1) AS '浪费%'
FROM information_schema.TABLES
WHERE table_schema = '你的库名'
ORDER BY data_free DESC LIMIT 10;

-- 3. ⚠️ 关键:查数据时间范围(决定能不能 TRUNCATE)
SELECT MIN(created_time), MAX(created_time), COUNT(*) FROM 你的库.你的表;

-- 4. OPTIMIZE(低峰期执行)
OPTIMIZE TABLE 你的库.你的表;

🎯 适合谁看?

场景推荐程度
MySQL 磁盘告警不知道怎么排查⭐⭐⭐⭐⭐
遇到过碎片但不确定 TRUNCATE 还是 OPTIMIZE⭐⭐⭐⭐⭐
想知道 data_free 怎么用⭐⭐⭐⭐
纯开发不碰数据库运维⭐⭐

💬 聊聊你的经历

  1. 你遇到过 MySQL 碎片占磁盘一半以上的情况吗?
  2. TRUNCATE 和 OPTIMIZE 之间你一般怎么选?有没有踩过坑?
  3. 你们会在巡检里加 data_free 监控吗?

原文链接 个人博客,欢迎关注交流 山外云的Vlog

模拟IC设计实战:折叠式共源共栅放大器的参数优化与噪声抑制 本文深入探讨了折叠式共源共栅放大器的核心设计要点。针对低电压下增益与输出摆幅的矛盾,文章详细阐述了从套筒式结构转向折叠式结构的必要性,并重点分析了其参数优化与噪声抑制的实战方法。通过手把手的参数计算流程,指导如何平衡增益、带宽、摆幅与功耗。同时,深入剖析了噪声来源,强调了采用PMOS输入对管以抑制1/f噪声,并提供了针对共栅管及电流镜的噪声优化策略,是模拟IC设计中高性能放大器设计的实用指南。 阅读详情

相关推荐

Windows10检查Cuda和cuDNN是否安装成功?

简介:根据上篇博客已经完成了CUDA和cuDNN的安装步骤,完成对其的安装。下面将来检查它们是否安装成功。 1 .首先win+R进入CMD,在命令行输入nvcc -V,如下图所示,则表示cuda已经安装成功。 2 .进入到cuda的安装路径,C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\extras\demo_suite,找到如下两个.exe文件: 首先执行:deviceQuery.exe,查看是否出现如下界面: 然后执行bandwid

jhsignal的博客 14万+

MySQL之表碎片化

因为删除表数据发现表使用空间未被释放,继而发现有表碎片问题,查找一些资料去了解表碎片的产生以及表碎片的处理,最终让自己学习到了关于InnoDB表碎片相关的知识。

AaronCao 4026

【AutoDL + Langchain-Chatchat】从零构建高效本地 RAG 知识库问答系统:实战保姆级教程(含避坑指南)

本文详细阐述如何在AutoDL云平台,如何利用Langchain-Chatchat构建高效的本地RAG知识库问答系统,并深入解析RAG架构。从环境搭建到实战部署,从问题排查到性能优化,提供一份全面实用的指南,助力开发者快速构建智能问答应用。

拾光夕拾的博客 1804

mysql 清理与查看表空间大小 碎片问题sql

OPTIMIZE TABLE命令可以重新组织表,清理碎片并优化表的性能。这个命令会重新创建表,并将数据按照物理顺序重新存储,从而消除碎片。ALTER TABLE语句重建索引也可以清理碎片。这个操作会重新创建表的索引,从而重新组织数据并消除碎片。查看表空间大小 碎片问题sql。

m0_45493525的博客 531

软件工程:数据字典

数据字典

永远怀着至诚之心拥抱世界 4277

Frida Stalker实战:如何用指令级追踪破解OLLVM混淆的AES算法

本文深入探讨了如何使用Frida Stalker进行指令级追踪,破解经过OLLVM混淆的AES算法。通过动态分析技术,逆向工程师可以精准识别控制流平坦化等混淆手段,还原算法逻辑,特别适用于移动安全领域的加密算法分析。文章提供了详细的配置指南、核心机制解析和实战案例,帮助读者掌握对抗高级代码混淆的有效方法。

weixin_29325955的博客 476

MySQL表空间碎片—产生原因、带来的问题以及如何解决

Innodb的最小物理存储分配单位是页(page),而UPDATE也可能导致页分裂,频繁的页分裂,页会变得稀疏,并且被不规则的填充,所以最终数据会有碎片。例如原始数据长度varchar(100),大规模更新数据长度为50,这样的话,有50的空间被空白了,新入库的数据不能完全利用剩余的50,这就会产生碎片。当执行插入操作时,MySQL会尝试使用空白空间,如果插入的数据刚好按照索引排序落在这个区间,可能会复用这个位置,但如果某个空白空间一直没有被大小合适的数据占用,仍然无法将其彻底占用,就形成了碎片;

weixin_43816711的博客 5287

gnuradio+b210实现FM收音机

gnuradio+b210实现FM收音机环境介绍FM接收1 Flow Graph2 变量参数FM发射1 Flow Graph 环境介绍 Name Version gnuradio 3.7.14.0 uhd 3.15.0.0 ubuntu 18.04 usrp b210 参考 https://www.ijedr.org/papers/IJEDR1702038.pdf Audio File Transmission using GNURADIO and USRP FM接

u011745228的博客 5127

mysql查看大小

1.查看所有数据库容量大小 select table_schema as '数据库', sum(table_rows) as '记录数', sum(truncate(data_length/1024/1024, 2)) as '数据容量(MB)', sum(truncate(index_length/1024/1024, 2)) as '索引容量(MB)' from in...

weixin_30251829的博客 922

结合qtdesigner,用pyqtgraph在界面上绘制波形图(一)

思路:先画图,然后在qtdesigner上放一个容器,给这个容器添加一个布局,然后把图当作一个Widget放入布局中。二、PyUIC把test.ui转换成test.py,再新建一个load_test.py写脚本。就这么简单,基础部分就完成了。也可以给它添加样式,我知道的样式不算多,但会继续写。一、随便拖进来一个容器控件,我拖了一个Widget。要想把波形图显示在界面上,核心思想其实很简单。三、load_test.py的代码。

learninger_lt7的博客 1804

【知识分享】CAN总线中终端网络的重要性

P沟道和N沟道晶体管的漏源通态电阻匹配良好时,形成的CANH和CANL信号匹配良好;如果驱动器的一半具有比另一半低得多的导通状态电阻,那么总线共模电压将从VCC/2的显性状态偏离,并回到VCC/2的隐性状态,这将导致每一次状态转换都会伴随着共模电压噪声,从而导致更高水平的传导和辐射能量发射。

一只豌豆象的博客 1545

MySQL空间管理:查询、优化与碎片清理

定期分析和优化 MySQL 表空间,清理磁盘碎片,从而保持数据库的高效运行。Shell 脚本的自动化处理可以减少手动维护的负担,确保数据库始终处于最佳状态。

promise524的博客 2017

YOLOv11改进策略【模型轻量化】| 替换轻量化骨干网络:ShuffleNet V1

本文记录的是基于ShuffleNet V1的YOLOv11轻量化改进方法研究。ShuffleNet利用和操作降低计算成本,克服了现有先进架构在极小网络中因 1×1 卷积计算成本高而效率低的问题。相比一些传统的网络架构,能更好地。本文配置了原论文中和四种模型,以满足不同的需求。

Limiiiing的博客 1231

工作中使用到的单词(软件开发)_第五版

本文摘要: 本文为软件开发相关的术语与技术要点整理,主要包含2020-2025年间四版内容更新(No.01-41)。重点包括: 证书文件格式(PEM/P12)差异 外部API通信注意事项(Accept头设置、HTTPS连接问题) Postman工具使用技巧(Cookie管理、请求头设置) WAS配置相关经验(JVM设置、SSL连接问题) 数据库操作命令(DB2表结构修改) IBM安全管理组件(TAM/iv-user机制) 网络通信细节(chunked传输编码特性) 常用开发工具(curl、Postman)的

sun0322 2521

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

mysql 如何查询碎片_MySQL数据碎片的整理和分析

MySQL具有相当多不同种类的存储引擎来实现列表中的数据存储功能。每当MySQL从你的列表中删除了一行内容,该段空间就会被留空。而在一段时间内的大量删除操作,会使这种留空的空间变得比存储列表内容所使用的空间更大。当MySQL对数据进行扫描时,它扫描的对象实际是列表的容量需求上限,也就是数据被写入的区域中处于峰值位置的部分。如果进行新的插入操作,MySQL将尝试利用这些留空的区域,但仍然无法将其彻底...

weixin_39789499的博客 1010

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Mysql 查看数据库各个表占用空间

这篇文章主要给大家介绍了关于如何使用mysql语句查看数据库表所占容量空间大小的相关资料,如何在MySQL数据库管理中查询数据库、表、索引的容量大小是经常遇到的需求,需要的朋友可以参考下

龙井的专栏 1万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

MySQL查看表大小、磁盘空间占用最全方法(精准统计含索引、碎片、物理空间)

日常开发和运维中,很多人只会简单查询数据表数据量,却忽略了索引空间、空闲碎片、日志占用,导致出现诸多问题:单表数据量不大但磁盘爆满、数据库读写卡顿、扩容预判失误、归档清理后空间不释放等。不同于全局数据库容量查询,数据表级别的空间统计更精细化,是大表优化、分表改造、数据归档、磁盘扩容评估的核心依据。本文摒弃冗余理论,全程干货实操,区分InnoDB和MyISAM引擎差异,解决表空间统计不准、碎片看不到、物理空间无法核对等常见痛点,所有语句兼容主流MySQL版本,可直接复制运行。

ULIi096kr的博客 254

Mysql查询库、表、索引、碎片大小

Mysql

独孤飞磊 1285

MySQL表空间碎片

MySQL 表空间碎片

暗星涌动 3724

查看mysql表的碎片率,及优化方法

查看mysql表的碎片率: SELECT TABLE_SCHEMA ,TABLE_NAME ,ENGINE ,ROUND(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) AS SIZE_MB ,ROUND(DATA_FREE/1024/1024,2) AS FREE_SIZ_MB FROM information_schema.TABLES WHERE DATA_FREE >=5*1024*1024

阳水平的博客 3269

MySQL的表碎片处理

一、表碎片的产生 对于mysql表数据,当你delete掉很多数据时,这些数据占用的磁盘空间可能并不会立刻被回收;比如一张表有10G的数据,delete掉1G数据后,再查看表ibd文件会发现文件大小可能还是10G;如果这个表有insert操作的话,那么mysql就会优先考虑能不能将新数据存储到空白空间上,容易出现这样的情况:某个空白空间的大小是2MB,新...

weixin_33924312的博客 1018

mysql 查看碎片_MYSQL 碎片查询

查询库中碎片大于1G的所有表数据总大小:DATA_LENGTH+INDEX_LENGTH实际表空间大小:TABLE_ROWS*AVG_ROW_LENGTH碎片大小:(DATA_LENGTH+INDEX_LENGTH-TABLE_ROWS*AVG_ROW_LENGTH)/1024/1024/1024 碎片,单位G整理的SQL:select TABLE_SCHEMA,TABLE_NAME,ENGIN...

weixin_39639568的博客 1108

Mysql的表的碎片清理

最近在生成环境下的MySQL运行下降,有些sql执行也慢,首先检查下慢查询日志是否开启  show variables like ‘slow_query_log%’    在看慢日志设置的时间  show variables like ‘long_query_time%’;    可以看到开启了慢查询,find / -name slow-query.log查找慢日志  发现里面的sq

zhoulixin8的专栏 2368

查找mysql数据库碎片程度高的表

主要用到了两个表: nformation_schema.tables information_schema.INNODB_SYS_TABLESPACES 结合innodb_sys_tablespaces的字段FILE_SIZE计算表的物理文件大小和逻辑大小。 表的大小逻辑计算为data_length+index_length=xxx,假设是A左右,而物理文件大小是B左右,那么碎片率大约是 (B-A)/60*100% 碎片程度高的表: 下面大家也可以把基数调整的稍大一些为1.1,然后以这个为基线来做统计。

jiedaodezhuti的博客 954

mysql表碎片的查询自己回收

在MySQL中,我们经常会使用VARCHAR、TEXT、BLOB等可变长度的文本数据类型。不过,当我们使用这些数据类型之后,我们就不得不做一些额外的工作——MySQL数据表碎片整理。 每当MySQL从你的列表中删除了一行...

cj990133的博客 357
上一篇: 博客上线5天,我搭了个安全运营中
下一篇: DeepSeek V4 Pro 正式版来了:DeepSWE 暴涨近 5 倍,Codex 一条命令直连
hellojackyleon
博客等级 码龄18年 0粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值