外观
MySQL 数据库空间监控
概述
MySQL 数据库空间监控是保障数据库系统稳定运行的重要环节,通过实时监控数据库的存储空间使用情况,可以及时发现空间不足的风险,避免因空间耗尽导致的业务中断。本文档将详细介绍 MySQL 数据库空间监控的完整方案,包括监控内容、监控工具、监控脚本、告警策略和最佳实践,兼顾不同 MySQL 版本的差异。
空间监控的重要性
核心价值
- 预防业务中断:避免因空间耗尽导致的数据库服务中断
- 优化资源利用:合理分配和利用存储空间
- 规划容量扩展:为容量扩展提供数据支持
- 降低存储成本:避免过度存储和浪费
- 提高系统性能:避免因空间不足导致的性能下降
- 确保数据完整性:避免因空间不足导致的数据丢失
监控目标
| 监控目标 | 具体内容 |
|---|---|
| 实时监控 | 实时监控存储空间的使用情况 |
| 趋势分析 | 分析存储空间的增长趋势 |
| 告警通知 | 在空间不足时及时发出告警 |
| 容量预测 | 预测未来的存储空间需求 |
| 异常检测 | 检测存储空间的异常增长 |
| 报表生成 | 生成存储空间使用报表 |
空间监控内容
系统级空间监控
磁盘空间监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 磁盘使用率 | 磁盘的总体使用率 | 超过 80% 警告,超过 90% 严重 |
| 可用空间 | 磁盘的可用空间大小 | 低于 10GB 警告,低于 5GB 严重 |
| 空间增长速率 | 磁盘空间的增长速率 | 日增长超过 10% 警告 |
| 磁盘 IOPS | 磁盘的 IOPS 使用率 | 超过 80% 警告 |
| 磁盘吞吐量 | 磁盘的吞吐量使用率 | 超过 80% 警告 |
文件系统监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 文件系统类型 | 文件系统的类型(如 ext4、xfs) | 无 |
| 文件系统挂载点 | 文件系统的挂载点 | 无 |
| 文件系统大小 | 文件系统的总大小 | 无 |
| 文件系统可用空间 | 文件系统的可用空间 | 低于 10% 警告,低于 5% 严重 |
| 文件系统 inode 使用率 | 文件系统的 inode 使用率 | 超过 80% 警告,超过 90% 严重 |
数据库级空间监控
数据目录监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 数据目录大小 | MySQL 数据目录的总大小 | 无 |
| 数据目录使用率 | 数据目录所在磁盘的使用率 | 超过 80% 警告,超过 90% 严重 |
| 数据目录增长速率 | 数据目录的增长速率 | 日增长超过 10% 警告 |
日志目录监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 日志目录大小 | MySQL 日志目录的总大小 | 无 |
| 日志目录使用率 | 日志目录所在磁盘的使用率 | 超过 80% 警告,超过 90% 严重 |
| 日志生成速率 | 日志文件的生成速率 | 日增长超过 50GB 警告 |
临时目录监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 临时目录大小 | MySQL 临时目录的总大小 | 无 |
| 临时目录使用率 | 临时目录所在磁盘的使用率 | 超过 80% 警告,超过 90% 严重 |
| 临时文件数量 | 临时目录中的文件数量 | 超过 1000 个警告 |
数据库对象级空间监控
数据库大小监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 数据库总大小 | 单个数据库的总大小(数据 + 索引) | 无 |
| 数据库增长速率 | 数据库的增长速率 | 日增长超过 10% 警告 |
| 最大数据库 | 系统中最大的数据库 | 无 |
表大小监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 表总大小 | 单个表的总大小(数据 + 索引) | 超过 100GB 警告 |
| 表数据大小 | 表的数据大小 | 无 |
| 表索引大小 | 表的索引大小 | 无 |
| 表增长速率 | 表的增长速率 | 日增长超过 20% 警告 |
| 最大表 | 系统中最大的表 | 无 |
| 表碎片率 | 表的碎片率 | 超过 30% 警告 |
索引大小监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 索引总大小 | 单个索引的总大小 | 无 |
| 索引增长速率 | 索引的增长速率 | 日增长超过 20% 警告 |
| 最大索引 | 系统中最大的索引 | 无 |
| 索引使用率 | 索引的使用频率 | 使用率低于 1% 警告 |
日志文件监控
| 监控项 | 描述 | 告警阈值 |
|---|---|---|
| 二进制日志大小 | 单个二进制日志文件的大小 | 超过 1GB 警告 |
| 二进制日志总大小 | 所有二进制日志文件的总大小 | 超过 100GB 警告 |
| 错误日志大小 | 错误日志文件的大小 | 超过 100MB 警告 |
| 慢查询日志大小 | 慢查询日志文件的大小 | 超过 10GB 警告 |
| 审计日志大小 | 审计日志文件的大小 | 超过 50GB 警告 |
版本差异
MySQL 5.6
表空间管理:
- 只支持共享表空间和独立表空间
- 不支持临时表空间的独立管理
- 不支持 undo 表空间的独立管理
空间监控视图:
- information_schema.TABLES 视图功能有限
- 不支持 performance_schema 中的空间相关表
- 缺少 InnoDB 表空间的详细监控信息
日志管理:
- 二进制日志默认不压缩
- 慢查询日志只支持文本格式
- 不支持审计日志
监控限制:
- 缺少实时监控的系统变量
- 表碎片率计算不够准确
- 临时文件监控困难
MySQL 5.7
表空间管理:
- 支持独立临时表空间
- 支持独立 undo 表空间
- 支持 InnoDB 表空间压缩
空间监控视图:
- 增强了 information_schema.TABLES 视图
- 增加了 performance_schema 中的空间相关表
- 增加了 information_schema.INNODB_SYS_TABLESPACES 视图
- 增加了 information_schema.FILES 视图
日志管理:
- 支持二进制日志压缩
- 慢查询日志支持 JSON 格式
- 支持审计日志(企业版)
监控增强:
- 增加了实时监控的系统变量
- 表碎片率计算更准确
- 支持临时文件的监控
MySQL 8.0
表空间管理:
- 支持 InnoDB 通用表空间
- 支持 undo 表空间的自动管理
- 支持双写缓冲区压缩
- 支持 redo log 压缩
空间监控视图:
- 增强了 information_schema.INNODB_SYS_TABLESPACES 视图
- 增加了 information_schema.INNODB_TABLESPACES_BRIEF 视图
- 增加了 information_schema.INNODB_DATAFILES 视图
- 增强了 performance_schema 中的空间相关表
日志管理:
- 二进制日志压缩算法优化
- 慢查询日志支持更丰富的格式
- 审计日志功能增强
- 支持日志的自动轮转和清理
监控增强:
- 增加了更多实时监控的系统变量
- 支持更细粒度的空间监控
- 表碎片率计算更精确
- 支持临时表空间的详细监控
- 增加了 innodb_dedicated_server 参数,自动管理表空间
空间监控工具
系统级监控工具
| 工具名称 | 功能描述 | 适用场景 |
|---|---|---|
| df | 查看文件系统磁盘空间使用情况 | 简单的磁盘空间查看 |
| du | 查看目录和文件的磁盘空间使用情况 | 查看具体目录和文件的大小 |
| iostat | 监控系统 IO 情况 | 监控磁盘 IO 性能 |
| lsof | 查看打开的文件 | 查看占用磁盘空间的文件 |
| ncdu | 交互式磁盘空间分析工具 | 可视化分析磁盘空间使用情况 |
| Prometheus + Node Exporter | 监控系统级指标 | 全面的系统级监控 |
| Zabbix | 企业级监控解决方案 | 全面的系统和数据库监控 |
| Grafana | 数据可视化工具 | 可视化展示监控数据 |
数据库级监控工具
| 工具名称 | 功能描述 | 适用场景 |
|---|---|---|
| SHOW TABLE STATUS | 查看表的状态信息 | 查看表的基本信息和碎片率 |
| information_schema.TABLES | 查看表的详细信息 | 查看表的大小、行数等 |
| information_schema.INNODB_SYS_TABLESPACES | 查看 InnoDB 表空间信息 | 查看 InnoDB 表空间的大小和状态 |
| information_schema.FILES | 查看数据库文件信息 | 查看数据库文件的大小和位置 |
| mysqladmin | MySQL 管理工具 | 查看数据库的基本状态 |
| mysqldumpslow | 分析慢查询日志 | 分析慢查询日志的大小和内容 |
| Percona Toolkit | 一组 MySQL 管理工具 | 包括 pt-duplicate-key-checker、pt-index-usage 等 |
| Prometheus + MySQL Exporter | 监控 MySQL 指标 | 全面的 MySQL 监控 |
| MySQL Enterprise Monitor | 企业级 MySQL 监控工具 | 商业版 MySQL 监控解决方案 |
空间监控脚本
磁盘空间监控脚本
bash
#!/bin/bash
# 磁盘空间监控脚本
# 配置参数
ALERT_EMAIL="dba@example.com"
WARNING_THRESHOLD=80
CRITICAL_THRESHOLD=90
# 获取磁盘空间信息
echo "=== 磁盘空间监控报告 ==="
echo "报告生成时间: $(date +"%Y-%m-%d %H:%M:%S")"
echo ""
# 使用 df 命令获取磁盘空间信息
df -h | grep -v tmpfs | grep -v devtmpfs > /tmp/disk_space.txt
# 遍历每个磁盘分区
while read -r line; do
# 提取文件系统、大小、已用、可用、使用率、挂载点
FILESYSTEM=$(echo $line | awk '{print $1}')
SIZE=$(echo $line | awk '{print $2}')
USED=$(echo $line | awk '{print $3}')
AVAILABLE=$(echo $line | awk '{print $4}')
USAGE=$(echo $line | awk '{print $5}' | sed 's/%//')
MOUNT_POINT=$(echo $line | awk '{print $6}')
# 输出磁盘空间信息
echo "文件系统: $FILESYSTEM"
echo "大小: $SIZE"
echo "已用: $USED"
echo "可用: $AVAILABLE"
echo "使用率: ${USAGE}%"
echo "挂载点: $MOUNT_POINT"
echo ""
# 检查告警阈值
if [ $USAGE -ge $CRITICAL_THRESHOLD ]; then
# 严重告警
echo "ALERT: 磁盘 ${FILESYSTEM} 使用率达到 ${USAGE}%,挂载点 ${MOUNT_POINT},可用空间 ${AVAILABLE}" | mail -s "[严重告警] 磁盘空间不足" $ALERT_EMAIL
elif [ $USAGE -ge $WARNING_THRESHOLD ]; then
# 警告告警
echo "ALERT: 磁盘 ${FILESYSTEM} 使用率达到 ${USAGE}%,挂载点 ${MOUNT_POINT},可用空间 ${AVAILABLE}" | mail -s "[警告告警] 磁盘空间不足" $ALERT_EMAIL
fi
done < /tmp/disk_space.txt
# 清理临时文件
rm /tmp/disk_space.txt
echo "磁盘空间监控完成"目录空间监控脚本
bash
#!/bin/bash
# 目录空间监控脚本
# 配置参数
ALERT_EMAIL="dba@example.com"
CHECK_DIRS=("/var/lib/mysql" "/var/log/mysql" "/backup/mysql")
WARNING_THRESHOLD=100 # GB
CRITICAL_THRESHOLD=50 # GB
# 获取目录空间信息
echo "=== 目录空间监控报告 ==="
echo "报告生成时间: $(date +"%Y-%m-%d %H:%M:%S")"
echo ""
# 遍历每个目录
for DIR in "${CHECK_DIRS[@]}"; do
if [ -d "$DIR" ]; then
# 计算目录大小(GB)
SIZE_GB=$(du -s -B1 $DIR | awk '{print $1 / 1024 / 1024 / 1024}' | awk '{printf "%.2f", $1}')
# 输出目录空间信息
echo "目录: $DIR"
echo "大小: ${SIZE_GB} GB"
echo ""
# 转换为数值进行比较
SIZE_NUM=$(echo $SIZE_GB | sed 's/\.//')
WARNING_NUM=$(echo $WARNING_THRESHOLD | sed 's/\.//')
CRITICAL_NUM=$(echo $CRITICAL_THRESHOLD | sed 's/\.//')
# 检查告警阈值
if (( ${SIZE_NUM:0:${#WARNING_NUM}} >= $CRITICAL_NUM )); then
# 严重告警
echo "ALERT: 目录 $DIR 大小达到 ${SIZE_GB} GB,超过严重阈值 ${CRITICAL_THRESHOLD} GB" | mail -s "[严重告警] 目录空间不足" $ALERT_EMAIL
elif (( ${SIZE_NUM:0:${#WARNING_NUM}} >= $WARNING_NUM )); then
# 警告告警
echo "ALERT: 目录 $DIR 大小达到 ${SIZE_GB} GB,超过警告阈值 ${WARNING_THRESHOLD} GB" | mail -s "[警告告警] 目录空间不足" $ALERT_EMAIL
fi
else
echo "警告: 目录 $DIR 不存在"
echo ""
fi
done
echo "目录空间监控完成"数据库大小监控脚本
bash
#!/bin/bash
# 数据库大小监控脚本
# 配置参数
DB_HOST="localhost"
DB_USER="root"
DB_PASS="password"
ALERT_EMAIL="dba@example.com"
WARNING_THRESHOLD=100 # GB
CRITICAL_THRESHOLD=500 # GB
# 获取数据库大小信息
echo "=== 数据库大小监控报告 ==="
echo "报告生成时间: $(date +"%Y-%m-%d %H:%M:%S")"
echo "数据库实例: $DB_HOST"
echo ""
# 执行 SQL 查询获取数据库大小
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "
SELECT
table_schema AS database_name,
ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_size_gb,
ROUND(SUM(data_length) / 1024 / 1024 / 1024, 2) AS data_size_gb,
ROUND(SUM(index_length) / 1024 / 1024 / 1024, 2) AS index_size_gb,
COUNT(*) AS table_count
FROM
information_schema.tables
WHERE
table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
GROUP BY
table_schema
ORDER BY
total_size_gb DESC;
" > /tmp/database_size.txt
# 输出数据库大小信息
tail -n +2 /tmp/database_size.txt | while read -r line; do
# 提取数据库名称、总大小、数据大小、索引大小、表数量
DATABASE_NAME=$(echo $line | awk '{print $1}')
TOTAL_SIZE_GB=$(echo $line | awk '{print $2}')
DATA_SIZE_GB=$(echo $line | awk '{print $3}')
INDEX_SIZE_GB=$(echo $line | awk '{print $4}')
TABLE_COUNT=$(echo $line | awk '{print $5}')
# 输出数据库信息
echo "数据库名称: $DATABASE_NAME"
echo "总大小: ${TOTAL_SIZE_GB} GB"
echo "数据大小: ${DATA_SIZE_GB} GB"
echo "索引大小: ${INDEX_SIZE_GB} GB"
echo "表数量: $TABLE_COUNT"
echo ""
# 检查告警阈值
if (( $(echo "$TOTAL_SIZE_GB >= $CRITICAL_THRESHOLD" | bc -l) )); then
# 严重告警
echo "ALERT: 数据库 ${DATABASE_NAME} 大小达到 ${TOTAL_SIZE_GB} GB,超过严重阈值 ${CRITICAL_THRESHOLD} GB" | mail -s "[严重告警] 数据库空间不足" $ALERT_EMAIL
elif (( $(echo "$TOTAL_SIZE_GB >= $WARNING_THRESHOLD" | bc -l) )); then
# 警告告警
echo "ALERT: 数据库 ${DATABASE_NAME} 大小达到 ${TOTAL_SIZE_GB} GB,超过警告阈值 ${WARNING_THRESHOLD} GB" | mail -s "[警告告警] 数据库空间不足" $ALERT_EMAIL
fi
done
# 清理临时文件
rm /tmp/database_size.txt
echo "数据库大小监控完成"表大小监控脚本
bash
#!/bin/bash
# 表大小监控脚本
# 配置参数
DB_HOST="localhost"
DB_USER="root"
DB_PASS="password"
ALERT_EMAIL="dba@example.com"
WARNING_THRESHOLD=50 # GB
CRITICAL_THRESHOLD=100 # GB
TOP_N=10 # 只显示前 N 个最大的表
# 获取表大小信息
echo "=== 表大小监控报告 ==="
echo "报告生成时间: $(date +"%Y-%m-%d %H:%M:%S")"
echo "数据库实例: $DB_HOST"
echo "显示前 ${TOP_N} 个最大的表"
echo ""
# 执行 SQL 查询获取表大小
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "
SELECT
table_schema AS database_name,
table_name,
ROUND((data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_size_gb,
ROUND(data_length / 1024 / 1024 / 1024, 2) AS data_size_gb,
ROUND(index_length / 1024 / 1024 / 1024, 2) AS index_size_gb,
table_rows AS row_count,
ROUND(data_free / 1024 / 1024 / 1024, 2) AS free_space_gb,
ROUND((data_free / (data_length + index_length)) * 100, 2) AS fragmentation_pct
FROM
information_schema.tables
WHERE
table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
ORDER BY
total_size_gb DESC
LIMIT ${TOP_N};
" > /tmp/table_size.txt
# 输出表大小信息
tail -n +2 /tmp/table_size.txt | while read -r line; do
# 提取表信息
DATABASE_NAME=$(echo $line | awk '{print $1}')
TABLE_NAME=$(echo $line | awk '{print $2}')
TOTAL_SIZE_GB=$(echo $line | awk '{print $3}')
DATA_SIZE_GB=$(echo $line | awk '{print $4}')
INDEX_SIZE_GB=$(echo $line | awk '{print $5}')
ROW_COUNT=$(echo $line | awk '{print $6}')
FREE_SPACE_GB=$(echo $line | awk '{print $7}')
FRAGMENTATION_PCT=$(echo $line | awk '{print $8}')
# 输出表信息
echo "数据库名称: $DATABASE_NAME"
echo "表名称: $TABLE_NAME"
echo "总大小: ${TOTAL_SIZE_GB} GB"
echo "数据大小: ${DATA_SIZE_GB} GB"
echo "索引大小: ${INDEX_SIZE_GB} GB"
echo "行数: $ROW_COUNT"
echo "空闲空间: ${FREE_SPACE_GB} GB"
echo "碎片率: ${FRAGMENTATION_PCT}%"
echo ""
# 检查告警阈值
if (( $(echo "$TOTAL_SIZE_GB >= $CRITICAL_THRESHOLD" | bc -l) )); then
# 严重告警
echo "ALERT: 表 ${DATABASE_NAME}.${TABLE_NAME} 大小达到 ${TOTAL_SIZE_GB} GB,超过严重阈值 ${CRITICAL_THRESHOLD} GB" | mail -s "[严重告警] 表空间不足" $ALERT_EMAIL
elif (( $(echo "$TOTAL_SIZE_GB >= $WARNING_THRESHOLD" | bc -l) )); then
# 警告告警
echo "ALERT: 表 ${DATABASE_NAME}.${TABLE_NAME} 大小达到 ${TOTAL_SIZE_GB} GB,超过警告阈值 ${WARNING_THRESHOLD} GB" | mail -s "[警告告警] 表空间不足" $ALERT_EMAIL
fi
# 检查碎片率
if (( $(echo "$FRAGMENTATION_PCT >= 30" | bc -l) )); then
# 碎片率告警
echo "ALERT: 表 ${DATABASE_NAME}.${TABLE_NAME} 碎片率达到 ${FRAGMENTATION_PCT}%,建议进行优化" | mail -s "[警告告警] 表碎片率过高" $ALERT_EMAIL
fi
done
# 清理临时文件
rm /tmp/table_size.txt
echo "表大小监控完成"日志文件监控脚本
bash
#!/bin/bash
# 日志文件监控脚本
# 配置参数
DB_HOST="localhost"
DB_USER="root"
DB_PASS="password"
ALERT_EMAIL="dba@example.com"
BINLOG_WARNING_THRESHOLD=1 # GB
BINLOG_CRITICAL_THRESHOLD=2 # GB
LOG_WARNING_THRESHOLD=100 # MB
LOG_CRITICAL_THRESHOLD=500 # MB
# 获取日志文件信息
echo "=== 日志文件监控报告 ==="
echo "报告生成时间: $(date +"%Y-%m-%d %H:%M:%S")"
echo "数据库实例: $DB_HOST"
echo ""
# 获取数据目录
DATA_DIR=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW GLOBAL VARIABLES LIKE 'datadir';" | grep -v Variable_name | awk '{print $2}')
# 检查二进制日志文件
echo "=== 二进制日志文件 ==="
ls -lh ${DATA_DIR}binlog.* 2>/dev/null | sort -k5,5 -r > /tmp/binlog_files.txt
if [ -s /tmp/binlog_files.txt ]; then
cat /tmp/binlog_files.txt | while read -r line; do
# 提取二进制日志文件信息
FILE_SIZE=$(echo $line | awk '{print $5}')
FILE_NAME=$(echo $line | awk '{print $9}')
# 输出二进制日志文件信息
echo "文件名称: $FILE_NAME"
echo "文件大小: $FILE_SIZE"
echo ""
# 检查告警阈值
if [[ $FILE_SIZE =~ ^([0-9]+)G$ ]]; then
SIZE_GB=${BASH_REMATCH[1]}
if [ $SIZE_GB -ge $BINLOG_CRITICAL_THRESHOLD ]; then
# 严重告警
echo "ALERT: 二进制日志文件 $FILE_NAME 大小达到 ${SIZE_GB} GB,超过严重阈值 ${BINLOG_CRITICAL_THRESHOLD} GB" | mail -s "[严重告警] 二进制日志文件过大" $ALERT_EMAIL
elif [ $SIZE_GB -ge $BINLOG_WARNING_THRESHOLD ]; then
# 警告告警
echo "ALERT: 二进制日志文件 $FILE_NAME 大小达到 ${SIZE_GB} GB,超过警告阈值 ${BINLOG_WARNING_THRESHOLD} GB" | mail -s "[警告告警] 二进制日志文件过大" $ALERT_EMAIL
fi
fi
done
else
echo "没有找到二进制日志文件"
echo ""
fi
# 检查错误日志文件
echo "=== 错误日志文件 ==="
ERROR_LOG=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW GLOBAL VARIABLES LIKE 'log_error';" | grep -v Variable_name | awk '{print $2}')
if [ -f "$ERROR_LOG" ]; then
FILE_SIZE=$(du -h $ERROR_LOG | awk '{print $1}')
# 输出错误日志文件信息
echo "文件名称: $ERROR_LOG"
echo "文件大小: $FILE_SIZE"
echo ""
# 检查告警阈值
if [[ $FILE_SIZE =~ ^([0-9]+)M$ ]]; then
SIZE_MB=${BASH_REMATCH[1]}
if [ $SIZE_MB -ge $LOG_CRITICAL_THRESHOLD ]; then
# 严重告警
echo "ALERT: 错误日志文件 $ERROR_LOG 大小达到 ${SIZE_MB} MB,超过严重阈值 ${LOG_CRITICAL_THRESHOLD} MB" | mail -s "[严重告警] 错误日志文件过大" $ALERT_EMAIL
elif [ $SIZE_MB -ge $LOG_WARNING_THRESHOLD ]; then
# 警告告警
echo "ALERT: 错误日志文件 $ERROR_LOG 大小达到 ${SIZE_MB} MB,超过警告阈值 ${LOG_WARNING_THRESHOLD} MB" | mail -s "[警告告警] 错误日志文件过大" $ALERT_EMAIL
fi
elif [[ $FILE_SIZE =~ ^([0-9]+)G$ ]]; then
# 严重告警
echo "ALERT: 错误日志文件 $ERROR_LOG 大小达到 ${FILE_SIZE},超过严重阈值 ${LOG_CRITICAL_THRESHOLD} MB" | mail -s "[严重告警] 错误日志文件过大" $ALERT_EMAIL
fi
else
echo "没有找到错误日志文件"
echo ""
fi
# 检查慢查询日志文件
echo "=== 慢查询日志文件 ==="
SLOW_QUERY_LOG=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW GLOBAL VARIABLES LIKE 'slow_query_log_file';" | grep -v Variable_name | awk '{print $2}')
SLOW_QUERY_ENABLED=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW GLOBAL VARIABLES LIKE 'slow_query_log';" | grep -v Variable_name | awk '{print $2}')
if [ "$SLOW_QUERY_ENABLED" = "ON" ] && [ -f "$SLOW_QUERY_LOG" ]; then
FILE_SIZE=$(du -h $SLOW_QUERY_LOG | awk '{print $1}')
# 输出慢查询日志文件信息
echo "文件名称: $SLOW_QUERY_LOG"
echo "文件大小: $FILE_SIZE"
echo ""
# 检查告警阈值
if [[ $FILE_SIZE =~ ^([0-9]+)G$ ]]; then
# 严重告警
echo "ALERT: 慢查询日志文件 $SLOW_QUERY_LOG 大小达到 ${FILE_SIZE},建议清理或分析" | mail -s "[警告告警] 慢查询日志文件过大" $ALERT_EMAIL
fi
else
echo "慢查询日志未启用或文件不存在"
echo ""
fi
# 清理临时文件
rm -f /tmp/binlog_files.txt
echo "日志文件监控完成"空间监控告警策略
告警分级
| 告警级别 | 描述 | 通知方式 | 响应时间 |
|---|---|---|---|
| 严重告警 | 空间不足,可能导致业务中断 | 短信、电话、邮件 | 立即响应(30分钟内) |
| 警告告警 | 空间使用率较高,需要关注 | 邮件 | 24小时内响应 |
| 信息告警 | 空间使用情况正常,仅作通知 | 日志记录 | 无 |
告警通知方式
| 通知方式 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| 邮件 | 所有告警级别 | 详细信息、可追溯 | 可能被忽略 |
| 短信 | 严重告警 | 即时性强 | 信息有限、成本较高 |
| 电话 | 严重告警 | 即时性最强 | 成本高、可能打扰 |
| 即时通讯工具 | 所有告警级别 | 即时性强、成本低 | 信息有限 |
| 监控平台 | 所有告警级别 | 集中管理、可视化 | 需要登录平台查看 |
告警抑制
- 重复告警抑制:避免同一告警的重复发送
- 关联告警合并:合并相关的告警信息
- 非工作时间告警升级:非工作时间的告警升级为更高优先级
- 告警静默期:在维护窗口期设置告警静默
空间监控最佳实践
监控频率
| 监控对象 | 监控频率 | 建议 |
|---|---|---|
| 磁盘空间 | 每 5-15 分钟 | 实时监控,及时发现问题 |
| 数据库大小 | 每 1 小时 | 定期监控,了解增长趋势 |
| 表大小 | 每 6 小时 | 定期监控,发现大表和异常增长 |
| 日志文件 | 每 1 小时 | 定期监控,避免日志文件过大 |
| 碎片率 | 每天 | 定期检查,及时优化碎片 |
空间优化策略
数据归档:
- 将历史数据归档到低成本存储
- 使用分区表管理历史数据
- 定期清理过期数据
表优化:
- 优化表结构,减少冗余字段
- 清理表碎片
- 优化索引,删除无用索引
日志管理:
- 配置合理的二进制日志保留时间
- 定期清理慢查询日志
- 配置合理的错误日志级别
存储优化:
- 使用压缩表减少存储空间
- 使用高效的存储引擎(如 InnoDB)
- 实施分层存储策略
备份优化:
- 配置合理的备份保留时间
- 使用增量备份减少存储空间
- 备份文件压缩存储
自动化监控
- 自动化脚本:使用脚本自动收集和分析空间数据
- 监控平台:部署专业的监控平台
- 自动告警:配置自动告警规则
- 自动报表:生成自动化的空间使用报表
- 自动优化:实现部分空间优化的自动化
容量规划
- 趋势分析:分析空间增长趋势
- 容量预测:预测未来的空间需求
- 扩展计划:制定存储空间扩展计划
- 预算规划:为存储扩展制定预算
- 技术选型:选择合适的存储技术和架构
空间监控案例
案例背景
某电商公司的 MySQL 数据库,每天处理大量的订单和用户数据,存储空间增长迅速。为了避免因空间不足导致的业务中断,需要实施有效的空间监控方案。
监控方案设计
监控内容:
- 磁盘空间使用率
- 数据库大小和增长速率
- 表大小和碎片率
- 日志文件大小
监控工具:
- Prometheus + Node Exporter:监控系统级空间
- Prometheus + MySQL Exporter:监控数据库级空间
- Grafana:可视化展示监控数据
- 自定义监控脚本:补充监控内容
告警策略:
- 磁盘使用率超过 80% 发送警告邮件
- 磁盘使用率超过 90% 发送严重告警(短信 + 邮件)
- 表大小超过 100GB 发送警告邮件
- 表碎片率超过 30% 发送警告邮件
优化策略:
- 实施数据归档,将超过 6 个月的历史数据归档
- 定期清理过期的二进制日志和慢查询日志
- 每月优化一次表碎片
- 优化索引,删除无用索引
实施效果
- 避免了业务中断:及时发现并处理了多次空间不足的风险
- 优化了资源利用:通过归档和优化,减少了 30% 的存储空间占用
- 提高了系统性能:通过清理碎片和优化索引,提高了查询性能
- 降低了存储成本:避免了不必要的存储扩展
- 提高了运维效率:自动化监控和告警减少了人工干预
常见问题与解决方案
空间监控数据不准确
问题:监控到的空间数据与实际不符
解决方案:
- 检查监控脚本的准确性
- 确保监控工具的配置正确
- 定期校准监控数据
- 使用多种监控工具进行对比
- 考虑 MySQL 版本差异对监控数据的影响
告警频繁误报
问题:经常收到不必要的空间告警
解决方案:
- 调整告警阈值,适应业务需求
- 实施告警抑制策略
- 优化监控脚本,减少误报
- 定期审查告警规则
- 考虑业务的季节性变化
空间增长异常
问题:存储空间增长异常迅速
解决方案:
- 分析空间增长的原因
- 检查是否有异常的数据插入
- 检查日志文件是否过大
- 检查是否有临时表或中间表占用过多空间
- 检查是否有备份或其他操作占用空间
表碎片率过高
问题:表的碎片率过高
解决方案:
- 定期优化表碎片
- 使用 OPTIMIZE TABLE 或 ALTER TABLE ... FORCE
- 对于大表,考虑使用 pt-online-schema-change 进行在线优化
- 调整表的存储引擎或参数
- 考虑使用分区表减少碎片
日志文件过大
问题:日志文件(如二进制日志、慢查询日志)过大
解决方案:
- 配置合理的日志保留时间
- 定期清理过期的日志文件
- 调整日志的生成策略
- 考虑使用日志轮转工具
- 对于 MySQL 8.0,使用自动日志清理功能
总结
MySQL 数据库空间监控是保障数据库系统稳定运行的重要环节,通过实时监控和分析存储空间的使用情况,可以及时发现空间不足的风险,避免因空间耗尽导致的业务中断。本文档详细介绍了 MySQL 数据库空间监控的完整方案,包括监控内容、监控工具、监控脚本、告警策略和最佳实践,并兼顾了 MySQL 5.6/5.7/8.0 的版本差异。
空间监控是一个持续的过程,需要定期审查和调整监控策略,以适应业务的变化和增长。通过实施有效的空间监控方案,可以优化资源利用,降低存储成本,提高系统性能,确保数据完整性,为业务的稳定运行提供保障。
DBA 团队应根据实际情况,选择合适的监控工具和策略,实施全面的空间监控,确保数据库系统的稳定运行和可持续发展。
