Skip to content

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查看数据库文件信息查看数据库文件的大小和位置
mysqladminMySQL 管理工具查看数据库的基本状态
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 小时定期监控,避免日志文件过大
碎片率每天定期检查,及时优化碎片

空间优化策略

  1. 数据归档

    • 将历史数据归档到低成本存储
    • 使用分区表管理历史数据
    • 定期清理过期数据
  2. 表优化

    • 优化表结构,减少冗余字段
    • 清理表碎片
    • 优化索引,删除无用索引
  3. 日志管理

    • 配置合理的二进制日志保留时间
    • 定期清理慢查询日志
    • 配置合理的错误日志级别
  4. 存储优化

    • 使用压缩表减少存储空间
    • 使用高效的存储引擎(如 InnoDB)
    • 实施分层存储策略
  5. 备份优化

    • 配置合理的备份保留时间
    • 使用增量备份减少存储空间
    • 备份文件压缩存储

自动化监控

  • 自动化脚本:使用脚本自动收集和分析空间数据
  • 监控平台:部署专业的监控平台
  • 自动告警:配置自动告警规则
  • 自动报表:生成自动化的空间使用报表
  • 自动优化:实现部分空间优化的自动化

容量规划

  • 趋势分析:分析空间增长趋势
  • 容量预测:预测未来的空间需求
  • 扩展计划:制定存储空间扩展计划
  • 预算规划:为存储扩展制定预算
  • 技术选型:选择合适的存储技术和架构

空间监控案例

案例背景

某电商公司的 MySQL 数据库,每天处理大量的订单和用户数据,存储空间增长迅速。为了避免因空间不足导致的业务中断,需要实施有效的空间监控方案。

监控方案设计

  1. 监控内容

    • 磁盘空间使用率
    • 数据库大小和增长速率
    • 表大小和碎片率
    • 日志文件大小
  2. 监控工具

    • Prometheus + Node Exporter:监控系统级空间
    • Prometheus + MySQL Exporter:监控数据库级空间
    • Grafana:可视化展示监控数据
    • 自定义监控脚本:补充监控内容
  3. 告警策略

    • 磁盘使用率超过 80% 发送警告邮件
    • 磁盘使用率超过 90% 发送严重告警(短信 + 邮件)
    • 表大小超过 100GB 发送警告邮件
    • 表碎片率超过 30% 发送警告邮件
  4. 优化策略

    • 实施数据归档,将超过 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 团队应根据实际情况,选择合适的监控工具和策略,实施全面的空间监控,确保数据库系统的稳定运行和可持续发展。