案例:预判磁盘爆满,提前 30 天预警¶
场景背景¶
- 时间:2026-06-18
- 角色:运维工程师,管理 3 台 MySQL 服务器
- 现状:jump 库磁盘使用率 55%,按当前增速预估 60 天后爆满
- 目标:用 dbskiter 预测容量趋势,提前规划扩容或数据归档
- 痛点:以前靠"经验感觉"判断,多次深夜磁盘告警紧急处理
生活化比喻:磁盘容量就像汽车油箱。你不仅要"当前油量 55%",还要知道"油耗 2L/天",才能算出"还能跑多少天"。dbskiter 的容量预测就是"智能油耗计算器"。
步骤 1:获取当前容量快照(30 秒)¶
dbskiter --database=jump monitor capacity --resource=disk
输出:
容量快照(磁盘):
====================================
数据库: jump
磁盘总容量: 100 GB
磁盘已使用: 55 GB (55%)
数据库数据: 23.4 GB
索引文件: 4.8 GB
日志文件: 12.3 GB (binlog)
其他占用: 14.5 GB (备份、系统日志等)
可用空间: 45 GB
步骤 2:容量预测(1 分钟)¶
dbskiter --database=jump monitor capacity-advanced --resource=disk
输出:
容量预测(未来 90 天):
====================================
当前状态:
数据库大小: 23.4 GB
磁盘使用率: 55%
可用空间: 45 GB
历史增长趋势(最近 30 天):
日均增长: 0.45 GB/天
周均增长: 3.15 GB/周
月增长: 13.5 GB/月
预测(线性模型):
7 天后: 26.6 GB 数据库 / 58.2 GB 磁盘 (58%)
14 天后: 29.7 GB 数据库 / 61.3 GB 磁盘 (61%)
30 天后: 36.9 GB 数据库 / 68.5 GB 磁盘 (69%)
60 天后: 50.4 GB 数据库 / 82.0 GB 磁盘 (82%) ← 告警阈值
90 天后: 63.9 GB 数据库 / 95.5 GB 磁盘 (96%) ← 危险
预测(考虑业务增长 20%):
30 天后: 40.1 GB 数据库 / 71.7 GB 磁盘 (72%)
60 天后: 56.9 GB 数据库 / 88.5 GB 磁盘 (89%) ← 严重
90 天后: 76.1 GB 数据库 / 107.7 GB 磁盘 (108%) ← 已满!
风险等级:
线性增长: MEDIUM(60 天后达到 82%)
业务增长: HIGH(60 天后达到 89%,90 天爆满)
建议:
1. 30 天内评估扩容或数据归档方案
2. 60 天前完成扩容或清理历史数据
3. 设置告警阈值: 磁盘使用率 > 70% 预警,> 80% 紧急
步骤 3:查看历史趋势(1 分钟)¶
dbskiter --database=jump monitor trend --metric=disk_usage
输出:
磁盘使用趋势(最近 30 天):
====================================
日期 数据库大小 磁盘使用率 日增长
2026-05-19 10.2 GB 42% --
2026-05-26 13.1 GB 45% +0.41 GB/天
2026-06-02 16.8 GB 49% +0.53 GB/天
2026-06-09 20.5 GB 52% +0.53 GB/天
2026-06-16 23.4 GB 55% +0.41 GB/天
平均增长: 0.45 GB/天
增长率变化: 5 月后半月增长加速(从 0.41 → 0.53),近 1 周回落至 0.41
异常点检测:
2026-05-28: 日增长 1.2 GB(异常高)
可能原因: 全量数据导入或批量插入任务
分析:增长趋势不是匀速的。5 月底有一次异常增长(1.2 GB/天),可能是业务上线或数据迁移。最近一周回落到 0.41 GB/天,但需按保守值(0.53 GB/天)做规划。
步骤 4:分析增长来源(2 分钟)¶
哪些表在增长?¶
dbskiter --database=jump diagnose sql "
SELECT
table_name,
ROUND(data_length / 1024 / 1024 / 1024, 2) AS data_gb,
ROUND(index_length / 1024 / 1024 / 1024, 2) AS index_gb,
ROUND((data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_gb,
table_rows
FROM information_schema.tables
WHERE table_schema = 'jump'
ORDER BY (data_length + index_length) DESC
LIMIT 10;
"
输出:
表名 数据大小 索引大小 总计 行数
orders 8.50 GB 2.10 GB 10.60 GB 12,450,000
logs 6.20 GB 0.80 GB 7.00 GB 8,900,000
user_actions 3.10 GB 1.20 GB 4.30 GB 5,600,000
payment_records 2.80 GB 0.90 GB 3.70 GB 3,200,000
... ... ... ... ...
增长最快的表¶
dbskiter --database=jump diagnose sql "
SELECT
table_name,
table_rows,
ROUND(data_length / 1024 / 1024 / 1024, 2) AS total_gb,
ROUND(data_length / table_rows / 1024, 2) AS avg_row_kb
FROM information_schema.tables
WHERE table_schema = 'jump'
AND table_rows > 0
ORDER BY avg_row_kb DESC
LIMIT 5;
"
输出:
表名 行数 总计 平均行大小
logs 8,900,000 7.00 GB 0.82 KB ← 日志表,增长最快
user_actions 5,600,000 4.30 GB 0.78 KB
orders 12,450,000 10.60 GB 0.87 KB
关键发现: 1.
logs表虽然行数不是最多,但增长最快(日志不断写入) 2.orders表最大(10.6 GB),但增长相对稳定(业务增长驱动) 3.user_actions表(行为日志)也是增长大户
步骤 5:制定扩容/归档方案(5 分钟)¶
方案对比¶
| 方案 | 成本 | 实施周期 | 风险 | 适用场景 |
|---|---|---|---|---|
| 磁盘扩容 | 云服务按量付费 | 1 天 | 低 | 业务持续增长,长期方案 |
| 历史数据归档 | 开发人力 | 1-2 周 | 中 | 有冷数据可移出 |
| 日志表清理 | 零成本 | 1 天 | 低 | 日志有保留期限 |
| 表分区 | 开发人力 | 2-4 周 | 中 | 大表按时间分区,可删旧分区 |
| 压缩存储 | 性能损耗 5-10% | 1 天 | 低 | 读多写少,CPU 有余量 |
推荐方案:组合策略¶
短期(1 周内):清理日志
-- 删除 90 天前的日志(确认业务允许)
DELETE FROM logs WHERE create_time < DATE_SUB(NOW(), INTERVAL 90 DAY);
-- 优化表空间回收(InnoDB)
OPTIMIZE TABLE logs;
-- 预期释放: 约 4-5 GB
中期(1 个月内):日志表分区
-- 按月份分区,方便清理旧数据
ALTER TABLE logs PARTITION BY RANGE (YEAR(create_time) * 100 + MONTH(create_time)) (
PARTITION p202405 VALUES LESS THAN (202406),
PARTITION p202406 VALUES LESS THAN (202407),
PARTITION p202407 VALUES LESS THAN (202408),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
-- 清理旧分区(秒级,不锁表)
ALTER TABLE logs DROP PARTITION p202405;
-- 预期每月释放: 1-2 GB
长期(3 个月内):磁盘扩容
# 云服务器扩容(以 AWS 为例)
aws ec2 modify-volume --volume-id vol-1234567890 --size 200
# 或阿里云
aliyun ecs ModifyDiskAttribute --DiskId d-1234567890 --Size 200
# 扩容后重启 MySQL,让它识别新空间
# 同时调整 innodb_buffer_pool_size 等参数
步骤 6:设置告警(自动化)¶
使用 dbskiter 定期巡检 + 脚本告警¶
#!/bin/bash
# /opt/scripts/disk_capacity_check.sh
THRESHOLD=70
CRITICAL=80
dbskiter --database=jump monitor capacity --resource=disk > /tmp/capacity.log
USAGE=$(grep "磁盘使用率" /tmp/capacity.log | awk '{print $2}' | tr -d '%')
echo "当前磁盘使用率: ${USAGE}%"
if [ "$USAGE" -ge "$CRITICAL" ]; then
# 发送紧急告警(企业微信/钉钉/邮件)
curl -X POST "https://oapi.dingtalk.com/robot/send?access_token=xxx" \
-H "Content-Type: application/json" \
-d "{\"msgtype\": \"text\", \"text\": {\"content\": \"[紧急] jump 数据库磁盘使用率 ${USAGE}%,已超过 80% 阈值!\"}}"
exit 2
elif [ "$USAGE" -ge "$THRESHOLD" ]; then
# 发送预警
curl -X POST "https://oapi.dingtalk.com/robot/send?access_token=xxx" \
-H "Content-Type: application/json" \
-d "{\"msgtype\": \"text\", \"text\": {\"content\": \"[预警] jump 数据库磁盘使用率 ${USAGE}%,预计 30 天后达到 80%。\"}}"
exit 1
else
echo "磁盘使用率正常: ${USAGE}%"
exit 0
fi
加入 crontab:
# 每天凌晨 3 点检查
0 3 * * * /opt/scripts/disk_capacity_check.sh >> /var/log/capacity_check.log 2>&1
验证方案效果¶
# 清理日志后重新检查
dbskiter --database=jump monitor capacity-advanced --resource=disk
预期结果:
| 项目 | 清理前 | 清理后 | 变化 |
|---|---|---|---|
| 数据库大小 | 23.4 GB | 18.5 GB | -4.9 GB |
| 磁盘使用率 | 55% | 48% | -7% |
| 预计爆满天数 | 60 天 | 90 天 | +30 天 |
| 风险等级 | MEDIUM | LOW | 降低 |
复盘要点¶
1. 容量规划口诀¶
看当前 → 算增速 → 预测未来 → 找增长来源 → 定方案 → 设告警
2. 关键判断指标¶
| 指标 | 含义 | 行动阈值 |
|---|---|---|
| 磁盘使用率 | 当前饱和度 | > 70% 预警,> 80% 紧急,> 90% 必须处理 |
| 日增长量 | 增长速度 | 用于预测 |
| 预计爆满天数 | 剩余时间 | < 30 天必须行动 |
| 增长来源表 | 谁在占用 | 定位优化对象 |
3. 预测模型选择¶
| 模型 | 适用场景 | 保守度 |
|---|---|---|
| 线性增长 | 业务稳定,无突发 | 中等 |
| 考虑业务增长 20% | 有促销、上线计划 | 较保守 |
| 考虑历史最大值 | 有突发增长记录 | 最保守 |
建议:按保守值做规划,宁可提前扩容,不要深夜告警。
4. 常见误区¶
| 误区 | 正确做法 |
|---|---|
| "磁盘 50% 还早,不急" | 按增长速度算,50% 如果增速快,30 天就 80% |
| "数据库大小 = 磁盘占用" | 磁盘还有 binlog、备份、日志,通常数据库只占 30-50% |
| "扩容是唯一方案" | 先清理日志/归档冷数据,零成本释放 20-40% 空间 |
| "预测不准,没用" | 预测是趋势判断,不是精确计算,目的是提前预警 |
| "等告警了再处理" | 告警时通常已经 80%+,此时处理时间紧迫 |