如何配置Monit监控MariaDB复制状态并发送异常告警
MariaDB/MySQL复制状态Monit监控方案
适配Monit 5.27.2版本(基于返回码判断状态,无需5.29+版本的输出匹配特性),兼容单源/多源复制架构,同时支持MariaDB、MySQL主流版本。
前置准备
- 数据库侧创建监控专用最小权限账号:
CREATE USER 'monit_check'@'localhost' IDENTIFIED BY '自定义强密码'; GRANT REPLICATION CLIENT ON *.* TO 'monit_check'@'localhost'; FLUSH PRIVILEGES;
- 配置数据库客户端本地免密登录,避免脚本硬编码密码,编辑
/root/.my.cnf(Monit默认以root身份执行检测脚本)写入如下内容:
[client] user=monit_check password=刚才设置的监控账号密码 socket=/run/mysqld/mysqld.sock
- 收紧配置文件权限,防止普通用户读取密码:
chmod 600 /root/.my.cnf
监控检测脚本
创建脚本文件/usr/local/bin/check_db_replication.sh,写入如下内容:
#!/bin/bash set -uo pipefail ERRORS=() # 延迟阈值,单位秒,可根据业务容忍度自行调整 DELAY_THRESHOLD=300 # 优先查询多源复制状态,旧版本不支持则自动fallback到单源查询语法 SLAVE_STATUS_RAW=$(mysql -B -e "SHOW ALL SLAVES STATUS\G" 2>/dev/null) if [ $? -ne 0 ] || [ -z "$SLAVE_STATUS_RAW" ]; then SLAVE_STATUS_RAW=$(mysql -B -e "SHOW SLAVE STATUS\G" 2>/dev/null) fi # 检测数据库连接状态 if [ $? -ne 0 ] || [ -z "$SLAVE_STATUS_RAW" ]; then echo "CRITICAL: 无法连接数据库实例,或当前实例未配置复制链路" exit 2 fi CURRENT_CHANNEL="" IO_RUNNING="" SQL_RUNNING="" LAST_ERROR="" SECONDS_BEHIND="" while IFS= read -r line; do # 匹配到新的复制链路块起始位置 if [[ "$line" == \** ]]; then # 校验上一个链路的状态(首次进入循环跳过空值) if [ -n "$CURRENT_CHANNEL" ]; then [ "$IO_RUNNING" != "Yes" ] && ERRORS+=("链路[$CURRENT_CHANNEL] IO线程异常,当前值:$IO_RUNNING") [ "$SQL_RUNNING" != "Yes" ] && ERRORS+=("链路[$CURRENT_CHANNEL] SQL线程异常,当前值:$SQL_RUNNING") [ -n "$LAST_ERROR" ] && ERRORS+=("链路[$CURRENT_CHANNEL] 复制报错:$LAST_ERROR") if [ "$SECONDS_BEHIND" == "NULL" ] || [ "$SECONDS_BEHIND" -gt $DELAY_THRESHOLD ] 2>/dev/null; then ERRORS+=("链路[$CURRENT_CHANNEL] 复制延迟过高/中断,当前延迟:$SECONDS_BEHIND秒") fi fi # 重置当前链路参数,单源复制默认链路名设为default CURRENT_CHANNEL="default" IO_RUNNING="" SQL_RUNNING="" LAST_ERROR="" SECONDS_BEHIND="" continue fi # 提取字段键值 key=$(echo "$line" | awk -F: '{print $1}' | xargs) value=$(echo "$line" | cut -d: -f2- | xargs) case "$key" in "Connection_name") [ -n "$value" ] && CURRENT_CHANNEL="$value" ;; "Slave_IO_Running") IO_RUNNING="$value" ;; "Slave_SQL_Running") SQL_RUNNING="$value" ;; "Last_Error") LAST_ERROR="$value" ;; "Seconds_Behind_Master") SECONDS_BEHIND="$value" ;; esac done <<< "$SLAVE_STATUS_RAW" # 校验最后一个复制链路的状态 if [ -n "$CURRENT_CHANNEL" ]; then [ "$IO_RUNNING" != "Yes" ] && ERRORS+=("链路[$CURRENT_CHANNEL] IO线程异常,当前值:$IO_RUNNING") [ "$SQL_RUNNING" != "Yes" ] && ERRORS+=("链路[$CURRENT_CHANNEL] SQL线程异常,当前值:$SQL_RUNNING") [ -n "$LAST_ERROR" ] && ERRORS+=("链路[$CURRENT_CHANNEL] 复制报错:$LAST_ERROR") if [ "$SECONDS_BEHIND" == "NULL" ] || [ "$SECONDS_BEHIND" -gt $DELAY_THRESHOLD ] 2>/dev/null; then ERRORS+=("链路[$CURRENT_CHANNEL] 复制延迟过高/中断,当前延迟:$SECONDS_BEHIND秒") fi fi # 返回结果与对应状态码 if [ ${#ERRORS[@]} -eq 0 ]; then echo "OK: 所有复制链路运行正常" exit 0 else echo "CRITICAL: 复制故障 - ${ERRORS[*]}" exit 1 fi
给脚本添加可执行权限:
chmod +x /usr/local/bin/check_db_replication.sh
可先手动执行脚本验证逻辑是否正常,复制正常时会返回OK: 所有复制链路运行正常。
Monit配置
在Monit配置目录(默认路径为/etc/monit/conf.d/)下新建配置文件db_replication,写入如下内容:
check program db_replication with path /usr/local/bin/check_db_replication.sh every 2 cycles # 状态异常即触发告警 if status != 0 then alert # 连续3个周期异常则自动重启数据库服务,不需要可删除该行 if status != 0 for 3 cycles then exec "/usr/bin/systemctl restart mariadb"
校验配置合法性并重载Monit生效:
monit -t systemctl reload monit
注:若监控的是MySQL服务,将上述配置中重启命令的
mariadb替换为mysqld即可。
测试验证
执行如下SQL模拟复制中断故障:
STOP SLAVE;
等待2-3个Monit检测周期(默认单周期30秒,即1-1.5分钟)即可收到告警,告警内容会明确标注异常链路、故障类型与错误信息。测试完成后执行START SLAVE;恢复复制,状态恢复正常后Monit会自动发送恢复通知。
内容的提问来源于stack exchange,提问作者luvzfootball
相关产品推荐
相关产品推荐

