跳转至

案例:预判磁盘爆满,提前 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%+,此时处理时间紧迫

延伸阅读