Shell脚本如何监控MySQL服务可用性

wen 实用脚本 1

Shell脚本监控MySQL服务可用性:从原理到生产级实践

目录导读

  1. 为什么需要监控MySQL服务可用性
  2. 监控核心指标与检测原理
  3. 基础Shell脚本实现
  4. 进阶技巧:连接池、超时与重试机制
  5. 常见问题与问答环节
  6. 生产环境部署建议

为什么需要监控MySQL服务可用性

在Web应用架构中,MySQL作为关系型数据库的核心组件,其可用性直接决定业务连续性,根据Statista 2024年数据,数据库故障导致的应用中断占全部运维事故的37%以上,传统人工检测方式存在以下痛点:

Shell脚本如何监控MySQL服务可用性

  • 延迟性:手动执行mysql命令可能错过间歇性故障
  • 盲区:无法检测到部分连接池耗尽但进程存活的“半可用”状态
  • 成本:7×24小时人工值守不现实

Shell脚本监控的优势在于轻量级、无依赖、可集成,适合作为第一道防线,但需注意:单纯检查进程是否存活(ps -ef | grep mysql)是无效的——进程僵尸化或锁死时,进程依然存在。


监控核心指标与检测原理

1 必须覆盖的四个维度

维度 检测命令 判断标准
进程存活 pgrep -x mysqld 返回PID号
端口监听 ss -tlnp | grep 3306 状态为LISTEN
连接能力 mysqladmin ping 返回"mysqld is alive"
查询响应 SELECT 1 1秒内返回结果

2 为什么不能只检查端口

一个反常识案例:某电商平台凌晨出现“MySQL连接超时”,检查发现3306端口正常监听,但连接数已达max_connections阈值(默认151),此时新连接被拒绝,但端口依然开放。端口检测只能证明mysqld进程启动,不能证明服务可用


基础Shell脚本实现

1 最简单的监控脚本(不足)

#!/bin/bash
mysql -u root -e "SELECT 1" &>/dev/null
if [ $? -eq 0 ]; then
    echo "MySQL可用"
else
    echo "MySQL不可用"
fi

问题:未处理数据库文件损坏、磁盘满导致的假死状态,更致命的是,如果MySQL被攻击后密码被改,此脚本无法正确反馈(因为仍返回0)。

2 生产级脚本(核心功能)

#!/bin/bash
# 配置参数(建议从环境变量读取)
MYSQL_USER="monitor"
MYSQL_PASS="monitor123"
MYSQL_HOST="127.0.0.1"
MYSQL_PORT="3306"
TIMEOUT=5
LOG_FILE="/var/log/monitor/mysql_health.log"
# 检测函数
check_mysql() {
    local result
    result=$(timeout $TIMEOUT mysqladmin ping -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" 2>&1)
    if echo "$result" | grep -q "alive"; then
        return 0
    else
        # 记录详细错误
        echo "$(date '+%Y-%m-%d %H:%M:%S') FAIL - $result" >> $LOG_FILE
        return 1
    fi
}
# 连续检测3次(避免偶发网络抖动)
FAIL_COUNT=0
for i in {1..3}; do
    if check_mysql; then
        FAIL_COUNT=0
        break
    else
        ((FAIL_COUNT++))
        sleep 2
    fi
done
# 输出结果(适合被Zabbix/Prometheus解析)
if [ $FAIL_COUNT -ge 3 ]; then
    echo "0"  # 0表示异常
    # 这里可插入告警:curl -X POST http://alert-api/...
else
    echo "1"  # 1表示正常
fi

关键设计

  • timeout命令防止网络卡死导致脚本挂起
  • 连续3次检测(间隔2秒)过滤抖动
  • 标准输出数值化,方便监控系统采集

进阶技巧:连接池、超时与重试机制

1 处理连接池耗尽

当MySQL连接数达到上限时,mysqladmin ping可能报错too many connections,此时需要额外检测:

# 检查当前连接数占比
CONN_PCT=$(mysqladmin -u root -p${PASS} status 2>/dev/null | awk '{print $4}' | tr -d '()')
# 示例输出:Threads: 145 (96% of max)
if [ $(echo "$CONN_PCT" | grep -oP '\d+(?=%)') -gt 90 ]; then
    echo "WARNING: 连接数超过90%"
fi

2 自定义超时应对慢查询

如果某条SQL卡死(如SELECT SLEEP(100)),普通检测会等待超时,使用异步检测

# 并行执行检测,限制总耗时
timeout 5 bash -c '
mysql -u $USER -p$PASS -e "SELECT 1" &
MYPID=$!
sleep 3 && kill $MYPID 2>/dev/null
wait $MYPID
' 2>/dev/null

3 重试机制的幂等性

告警触发后,避免重复通知,使用临时文件记录状态:

STATUS_FILE="/tmp/mysql_ok"
if [ $FAIL_COUNT -ge 3 ]; then
    if [ ! -f "$STATUS_FILE" ]; then
        echo "触发告警" 
        touch "$STATUS_FILE"
    fi
else
    rm -f "$STATUS_FILE" 2>/dev/null
fi

常见问题与问答环节

Q1:为什么用mysqladmin ping而不是mysqli

A:mysqladmin ping是最底层的心跳检测,不依赖账号权限(只需PROCESS权限),而mysql -e "SELECT 1"需要读取数据字典,在表损坏时可能失败。两者结合使用更安全:先用ping检测进程,再用SELECT 1验证查询能力。

Q2:监控脚本运行后占用资源吗?

A:单次执行消耗约0.01秒CPU时间和2MB内存,但在高并发系统中(如每5秒执行一次),累计影响显著。建议监控频率为30秒-60秒,并配合nice -n 19降低优先级。

Q3:如何监控主从延迟?

A:在从库执行show slave status\G,提取Seconds_Behind_Master,注意当主库异常时,该值为NULL,参考脚本:

SLAVE_STATUS=$(mysql -u $USER -p$PASS -e "SHOW SLAVE STATUS\G" 2>/dev/null)
IO_RUN=$(echo "$SLAVE_STATUS" | grep "Slave_IO_Running:" | awk '{print $2}')
SQL_RUN=$(echo "$SLAVE_STATUS" | grep "Slave_SQL_Running:" | awk '{print $2}')
if [ "$IO_RUN" != "Yes" ] || [ "$SQL_RUN" != "Yes" ]; then
    echo "主从同步中断"
fi

Q4:脚本部署到容器环境有什么注意事项?

A:Docker容器中可能缺少mysqladmin工具,建议使用mysql客户端命令:

# 替代mysqladmin ping
mysql -u $USER -p$PASS -e "STATUS;" | grep -q "Uptime:"

同时需注意容器内/var/log目录不可写的问题,建议日志输出到标准输出(echo)后由Docker日志驱动采集。


生产环境部署建议

  1. 权限最小化:创建专用监控账号

    CREATE USER 'monitor'@'127.0.0.1' IDENTIFIED BY 'password';
    GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'monitor'@'127.0.0.1';
  2. 集成到系统监控:写入crontab每30秒执行一次

    
    
        • root /usr/local/bin/mysql_monitor.sh

          • root sleep 30 && /usr/local/bin/mysql_monitor.sh
  1. 告警分级

    • 单次检测失败 → 日志记录(INFO)
    • 连续3次检测失败 → 触发告警(CRITICAL)
    • 恢复自动清除告警
  2. 压力测试:使用sysbench模拟高负载验证脚本稳定性

    # 模拟100个并发连接
    sysbench --threads=100 --time=60 oltp_read_only run
    # 同时监控脚本是否准确报出异常

延伸阅读:对于需要更高级功能的场景(如自动故障切换、慢查询追踪),建议评估Percona Monitoring and Management(PMM)或自研基于Shell+Python的混合监控方案,基础Shell脚本应作为第一响应层,与高级监控系统形成互补。

抱歉,评论功能暂时关闭!