内容简介:MySQL服务器告警是数据库运维的重要组成部分,对于保障数据库的高可用性、性能和稳定性至关重要。本文风哥教程参考MySQL官方文档MySQL Server Administration部分,详细介绍MySQL服务器告警的方法、工具和最佳实践,包括内置告警功能、第三方告警工具和自定义告警脚本的使用,以及告警系统的配置、管理和优化。学习交流加群风哥微信: itpux-com
Part01-基础概念与理论知识
1.1 MySQL告警概述
MySQL服务器告警是指当MySQL数据库出现异常情况或达到预设阈值时,自动发出通知的机制。告警的主要目标包括:
- 及时发现问题:在问题影响业务之前,及时发现并发出告警
- 减少故障影响:通过告警快速定位问题,减少故障影响范围和持续时间
- 提高运维效率:自动化告警机制可以减少人工监控的工作量,提高运维效率
- 保障业务连续性:通过及时处理告警,确保数据库服务的连续性和可用性
1.2 告警分类
MySQL告警可以根据不同的分类标准进行分类:
- 按告警内容分类:
- 性能告警:QPS/TPS过高、响应时间过长、慢查询过多等
- 资源告警:CPU使用率过高、内存不足、磁盘空间不足等
- 连接告警:连接数过多、连接超时、连接错误等
- 存储告警:表空间不足、索引碎片过多、数据文件损坏等
- 事务告警:事务长时间未提交、死锁、回滚比例过高等
- 复制告警:复制延迟、复制错误、主从不一致等
- 安全告警:异常登录、权限变更、SQL注入尝试等
- 按告警来源分类:
- 系统级告警:操作系统、硬件、网络等层面的告警
- 数据库级告警:MySQL数据库内部的告警
- 应用级告警:应用程序层面的告警
- 按告警方式分类:
- 内置告警:MySQL自带的告警功能
- 第三方告警:通过第三方监控工具实现的告警
- 自定义告警:通过自定义脚本实现的告警
1.3 告警级别
告警级别用于表示问题的严重程度,常见的告警级别包括:
- 紧急(Critical):数据库服务不可用,严重影响业务,需要立即处理
- 严重(Major):数据库性能严重下降,部分业务受到影响,需要尽快处理
- 警告(Warning):数据库出现异常情况,但暂时不影响业务,需要关注和处理
- 信息(Info):数据库运行状态的通知信息,不需要立即处理
Part02-生产环境规划与建议
2.1 告警策略规划
在生产环境中,MySQL告警策略的规划需要考虑以下因素:
- 告警对象:确定需要监控和告警的MySQL服务器、数据库和指标
- 告警阈值:根据业务需求和历史数据,设置合理的告警阈值
- 告警级别:根据问题的严重程度,设置不同的告警级别
- 告警通知:确定告警的通知方式(邮件、短信、即时通讯工具等)
- 告警接收人:根据告警级别和内容,确定不同级别的告警接收人
- 告警升级:设计告警升级机制,确保告警能够得到及时处理
- 告警抑制:避免同一问题产生过多重复告警
- 告警记录:记录所有告警信息,便于后续分析和改进
2.2 告警需求分析
在设计告警策略之前,需要进行告警需求分析,包括:
- 业务需求:了解业务对数据库可用性、性能和安全性的要求
- 系统架构:了解数据库系统的架构、规模和部署方式
- 历史数据:分析历史监控数据,确定正常和异常的阈值范围
- 运维流程:了解运维团队的工作流程和响应机制
- 资源约束:考虑运维团队的资源和能力,避免设置过多难以处理的告警
2.3 告警实现方式
MySQL告警的实现方式主要包括:
- 内置告警功能:MySQL自带的告警功能,如错误日志、慢查询日志等
- 第三方告警工具:专业的监控告警工具,如Nagios、Zabbix、Prometheus等
- 自定义告警脚本:通过编写脚本实现特定的告警需求
- 云服务告警:如果使用云服务,如AWS RDS、阿里云RDS等,可以使用云服务商提供的告警功能
Part03-生产环境项目实施方案
3.1 内置告警功能
MySQL提供了多种内置的告警功能,可以用于监控和告警。
3.1.1 错误日志告警
MySQL错误日志记录了数据库的错误信息和异常情况,可以通过监控错误日志实现告警。
mysql> SHOW GLOBAL VARIABLES LIKE ‘log_error’;
+—————+——————————+
| Variable_name | Value |
+—————+——————————+
| log_error | /var/lib/mysql/mysql-error.log |
+—————+——————————+
# 监控错误日志的脚本示例
#!/bin/bash
# monitor_error_log.sh
ERROR_LOG=”/var/lib/mysql/mysql-error.log”
ALERT_EMAIL=”dba@fgedu.net.cn”
# 监控最新的错误日志条目
NEW_ERRORS=$(tail -n 100 $ERROR_LOG | grep -i “error\|warning\|critical”)
if [ -n “$NEW_ERRORS” ]; then
echo “MySQL错误日志中发现新的错误/警告:” >> /tmp/mysql_error_alert.txt
echo “$NEW_ERRORS” >> /tmp/mysql_error_alert.txt
mail -s “MySQL错误日志告警” $ALERT_EMAIL < /tmp/mysql_error_alert.txt
rm -f /tmp/mysql_error_alert.txt
fi
# 使用crontab定时执行
echo "* * * * * /mysql/scripts/monitor_error_log.sh" >> /var/spool/cron/root
3.1.2 慢查询日志告警
慢查询日志记录了执行时间超过阈值的SQL语句,可以通过监控慢查询日志实现告警。
mysql> SHOW GLOBAL VARIABLES LIKE ‘slow_query_log’;
+—————-+——-+
| Variable_name | Value |
+—————-+——-+
| slow_query_log | ON |
+—————-+——-+
mysql> SHOW GLOBAL VARIABLES LIKE ‘slow_query_log_file’;
+———————+—————————+
| Variable_name | Value |
+———————+—————————+
| slow_query_log_file | /var/lib/mysql/slow.log |
+———————+—————————+
mysql> SHOW GLOBAL VARIABLES LIKE ‘long_query_time’;
+—————–+———-+
| Variable_name | Value |
+—————–+———-+
| long_query_time | 10.000000 |
+—————–+———-+
# 监控慢查询日志的脚本示例
#!/bin/bash
# monitor_slow_query.sh
SLOW_LOG=”/var/lib/mysql/slow.log”
ALERT_EMAIL=”dba@fgedu.net.cn”
THRESHOLD=5 # 每分钟慢查询数量阈值
# 获取当前时间和5分钟前的时间
CURRENT_TIME=$(date +”%s”)
FIVE_MINUTES_AGO=$(($CURRENT_TIME – 300))
# 计算5分钟内的慢查询数量
SLOW_QUERY_COUNT=$(grep -c “^# Time:” $SLOW_LOG | xargs -I {} echo “{}”)
if [ $SLOW_QUERY_COUNT -gt $THRESHOLD ]; then
echo “5分钟内慢查询数量超过阈值:$SLOW_QUERY_COUNT” >> /tmp/mysql_slow_alert.txt
echo “查看慢查询日志:$SLOW_LOG” >> /tmp/mysql_slow_alert.txt
tail -n 100 $SLOW_LOG >> /tmp/mysql_slow_alert.txt
mail -s “MySQL慢查询告警” $ALERT_EMAIL < /tmp/mysql_slow_alert.txt
rm -f /tmp/mysql_slow_alert.txt
fi
# 使用crontab定时执行
echo "*/5 * * * * /mysql/scripts/monitor_slow_query.sh" >> /var/spool/cron/root
3.2 第三方告警工具
除了内置告警功能外,还有许多第三方告警工具可以用于MySQL告警。
3.2.1 Nagios告警配置
Nagios是一款开源的监控系统,可以通过插件扩展支持MySQL告警。
# yum install nagios-plugins-mysql
# 配置MySQL监控命令
# vi /etc/nagios/objects/commands.cfg
define command {
command_name check_mysql_health
command_line $USER1$/check_mysql_health –hostname=$HOSTADDRESS$ –username=$ARG1$ –password=$ARG2$ –mode=$ARG3$ $ARG4$
}
# 配置MySQL服务告警
# vi /etc/nagios/objects/services.cfg
define service {
use generic-service
host_name mysql-server
service_description MySQL Connections
check_command check_mysql_health!nagios!password!connections! –warning=80 –critical=90
notification_options w,c,r
notification_interval 60
contact_groups admins
}
define service {
use generic-service
host_name mysql-server
service_description MySQL QPS
check_command check_mysql_health!nagios!password!questions! –warning=1000 –critical=2000
notification_options w,c,r
notification_interval 60
contact_groups admins
}
define service {
use generic-service
host_name mysql-server
service_description MySQL Slow Queries
check_command check_mysql_health!nagios!password!slow-queries! –warning=10 –critical=50
notification_options w,c,r
notification_interval 60
contact_groups admins
}
# 重启Nagios服务
# systemctl restart nagios
3.2.2 Zabbix告警配置
Zabbix是一款开源的企业级监控系统,提供对MySQL的全面告警支持。
# 1. 配置告警媒介类型
# 管理 > 媒介类型 > 创建媒体类型
# 类型:Email
# SMTP服务器:smtp.fgedu.net.cn
# SMTP服务器端口:25
# SMTP HELO:fgedu.net.cn
# SMTP电邮:zabbix@fgedu.net.cn
# 认证:无
# 点击”测试”按钮测试配置
# 2. 配置用户告警媒介
# 管理 > 用户 > 选择用户 > 媒介 > 添加
# 类型:Email
# 收件人:dba@fgedu.net.cn
# 当启用时:是
# 严重度:选择需要接收的告警级别
# 点击”更新”按钮保存配置
# 3. 配置告警动作
# 配置 > 动作 > 创建动作
# 名称:MySQL告警动作
# 默认接收人:选择用户组
# 默认信息:自定义告警信息
# 恢复信息:自定义恢复信息
# 条件:配置告警触发条件
# 操作:配置告警通知操作
# 点击”添加”按钮保存配置
# 4. 配置告警阈值
# 配置 > 主机 > 选择MySQL主机 > 触发器 > 选择触发器 > 更新
# 表达式:配置告警触发表达式
# 严重性:选择告警级别
# 点击”更新”按钮保存配置
3.2.3 Prometheus + Alertmanager告警配置
Prometheus是一款开源的监控和告警工具,Alertmanager用于处理Prometheus生成的告警。
# vi /etc/prometheus/rules/mysql_alerts.yml
groups:
– name: mysql_alerts
rules:
– alert: MySQLHighConnections
expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100 > 80
for: 5m
labels:
severity: warning
annotations:
summary: MySQL连接数过高 ({{ $labels.instance }})
description: MySQL连接使用率超过80% (当前: {{ $value | printf “%.2f” }}%)
– alert: MySQLHighConnectionsCritical
expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100 > 90
for: 5m
labels:
severity: critical
annotations:
summary: MySQL连接数严重过高 ({{ $labels.instance }})
description: MySQL连接使用率超过90% (当前: {{ $value | printf “%.2f” }}%)
– alert: MySQLSlowQueries
expr: rate(mysql_global_status_slow_queries[5m]) > 10
for: 5m
labels:
severity: warning
annotations:
summary: MySQL慢查询过多 ({{ $labels.instance }})
description: MySQL慢查询率超过10个/分钟 (当前: {{ $value | printf “%.2f” }}个/分钟)
– alert: MySQLHighBufferPoolUsage
expr: mysql_global_status_innodb_buffer_pool_pages_data / mysql_global_status_innodb_buffer_pool_pages_total * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: MySQL缓冲池使用率过高 ({{ $labels.instance }})
description: MySQL缓冲池使用率超过90% (当前: {{ $value | printf “%.2f” }}%)
# 配置Prometheus加载告警规则
# vi /etc/prometheus/prometheus.yml
rule_files:
– “/etc/prometheus/rules/mysql_alerts.yml”
# 配置Alertmanager
# vi /etc/alertmanager/alertmanager.yml
global:
smtp_smarthost: ‘smtp.fgedu.net.cn:25’
smtp_from: ‘alertmanager@fgedu.net.cn’
smtp_auth_username: ”
smtp_auth_password: ”
smtp_require_tls: false
route:
group_by: [‘alertname’, ‘instance’]
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
receiver: ‘dba-emails’
receivers:
– name: ‘dba-emails’
email_configs:
– to: ‘dba@fgedu.net.cn’
send_resolved: true
# 重启Prometheus和Alertmanager服务
# systemctl restart prometheus
# systemctl restart alertmanager
3.3 自定义告警脚本
除了使用现成的监控告警工具外,还可以编写自定义的告警脚本,满足特定的告警需求。
# mysql_alert.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
# MySQL配置信息
MYSQL_USER=”root”
MYSQL_PASS=”password”
MYSQL_HOST=”localhost”
MYSQL_PORT=”3306″
# 告警接收人
ALERT_EMAIL=”dba@fgedu.net.cn”
ALERT_PHONE=”13800138000″
# 告警阈值
CONNECTION_THRESHOLD=80 # 连接数使用率阈值(%)
QPS_THRESHOLD=1000 # QPS阈值
SLOW_QUERY_THRESHOLD=10 # 慢查询数阈值
BUFFER_POOL_THRESHOLD=90 # 缓冲池使用率阈值(%)
DISK_SPACE_THRESHOLD=90 # 磁盘空间使用率阈值(%)
# 获取当前时间
CURRENT_TIME=$(date ‘+%Y-%m-%d %H:%M:%S’)
# 初始化告警信息
ALERT_INFO=””
ALERT_SEVERITY=”info”
# 检查MySQL连接数
CONNECTION_COUNT=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL STATUS LIKE ‘Threads_connected’;” -N | awk ‘{print $2}’)
MAX_CONNECTION=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL VARIABLES LIKE ‘max_connections’;” -N | awk ‘{print $2}’)
CONNECTION_USAGE=$(echo “scale=2; $CONNECTION_COUNT / $MAX_CONNECTION * 100” | bc)
if (( $(echo “$CONNECTION_USAGE > $CONNECTION_THRESHOLD” | bc -l) )); then
ALERT_INFO=”$ALERT_INFO\n连接数使用率过高:${CONNECTION_USAGE}% (当前:${CONNECTION_COUNT},最大:${MAX_CONNECTION})”
ALERT_SEVERITY=”warning”
if (( $(echo “$CONNECTION_USAGE > $CONNECTION_THRESHOLD + 10″ | bc -l) )); then
ALERT_SEVERITY=”critical”
fi
fi
# 检查MySQL QPS
QUERIES=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL STATUS LIKE ‘Queries’;” -N | awk ‘{print $2}’)
UPTIME=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL STATUS LIKE ‘Uptime’;” -N | awk ‘{print $2}’)
if [ $UPTIME -gt 0 ]; then
QPS=$(echo “scale=2; $QUERIES / $UPTIME” | bc)
if (( $(echo “$QPS > $QPS_THRESHOLD” | bc -l) )); then
ALERT_INFO=”$ALERT_INFO\nQPS过高:${QPS} (阈值:${QPS_THRESHOLD})”
ALERT_SEVERITY=”warning”
fi
fi
# 检查MySQL慢查询数
SLOW_QUERIES=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL STATUS LIKE ‘Slow_queries’;” -N | awk ‘{print $2}’)
if (( $SLOW_QUERIES > $SLOW_QUERY_THRESHOLD )); then
ALERT_INFO=”$ALERT_INFO\n慢查询数过多:${SLOW_QUERIES} (阈值:${SLOW_QUERY_THRESHOLD})”
ALERT_SEVERITY=”warning”
fi
# 检查MySQL缓冲池使用率
BUFFER_POOL_DATA=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL STATUS LIKE ‘Innodb_buffer_pool_pages_data’;” -N | awk ‘{print $2}’)
BUFFER_POOL_TOTAL=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL STATUS LIKE ‘Innodb_buffer_pool_pages_total’;” -N | awk ‘{print $2}’)
if [ $BUFFER_POOL_TOTAL -gt 0 ]; then
BUFFER_POOL_USAGE=$(echo “scale=2; $BUFFER_POOL_DATA / $BUFFER_POOL_TOTAL * 100” | bc)
if (( $(echo “$BUFFER_POOL_USAGE > $BUFFER_POOL_THRESHOLD” | bc -l) )); then
ALERT_INFO=”$ALERT_INFO\n缓冲池使用率过高:${BUFFER_POOL_USAGE}% (阈值:${BUFFER_POOL_THRESHOLD}%)”
ALERT_SEVERITY=”warning”
fi
fi
# 检查磁盘空间使用率
MYSQL_DATA_DIR=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -h $MYSQL_HOST -P $MYSQL_PORT -e “SHOW GLOBAL VARIABLES LIKE ‘datadir’;” -N | awk ‘{print $2}’)
DISK_USAGE=$(df -h $MYSQL_DATA_DIR | tail -n 1 | awk ‘{print $5}’ | sed ‘s/%//’)
if (( $DISK_USAGE > $DISK_SPACE_THRESHOLD )); then
ALERT_INFO=”$ALERT_INFO\n磁盘空间使用率过高:${DISK_USAGE}% (目录:${MYSQL_DATA_DIR},阈值:${DISK_SPACE_THRESHOLD}%)”
ALERT_SEVERITY=”critical”
fi
# 发送告警
if [ -n “$ALERT_INFO” ]; then
# 构建告警标题
ALERT_SUBJECT=”[MySQL告警] ${ALERT_SEVERITY} – ${MYSQL_HOST}:${MYSQL_PORT}”
# 构建告警内容
ALERT_CONTENT=”MySQL告警信息\n”
ALERT_CONTENT=”${ALERT_CONTENT}====================\n”
ALERT_CONTENT=”${ALERT_CONTENT}告警时间:${CURRENT_TIME}\n”
ALERT_CONTENT=”${ALERT_CONTENT}告警级别:${ALERT_SEVERITY}\n”
ALERT_CONTENT=”${ALERT_CONTENT}MySQL实例:${MYSQL_HOST}:${MYSQL_PORT}\n”
ALERT_CONTENT=”${ALERT_CONTENT}告警信息:${ALERT_INFO}\n”
ALERT_CONTENT=”${ALERT_CONTENT}====================\n”
ALERT_CONTENT=”${ALERT_CONTENT}请及时处理!\n”
ALERT_CONTENT=”${ALERT_CONTENT}学习交流加群风哥微信: itpux-com\n”
# 发送邮件告警
echo -e “${ALERT_CONTENT}” | mail -s “${ALERT_SUBJECT}” ${ALERT_EMAIL}
# 如果是紧急告警,发送短信告警
if [ “$ALERT_SEVERITY” = “critical” ]; then
# 这里可以集成短信告警API
echo “发送短信告警:${ALERT_SUBJECT} ${ALERT_INFO}” >> /mysql/logs/alert_sms.log
fi
# 记录告警日志
echo “${CURRENT_TIME} ${ALERT_SUBJECT} ${ALERT_INFO}” >> /mysql/logs/mysql_alert.log
fi
# crontab -e
* * * * * /mysql/scripts/mysql_alert.sh
# 查看告警日志
# tail -n 10 /mysql/logs/mysql_alert.log
2026-04-03 22:00:00 [MySQL告警] warning – localhost:3306 连接数使用率过高:85.00% (当前:850,最大:1000)
2026-04-03 22:05:00 [MySQL告警] warning – localhost:3306 连接数使用率过高:86.00% (当前:860,最大:1000)
2026-04-03 22:10:00 [MySQL告警] critical – localhost:3306 连接数使用率过高:95.00% (当前:950,最大:1000)
3.4 告警系统集成
将MySQL告警与其他系统集成,可以提高告警的处理效率和自动化程度。
#!/bin/bash
# mysql_wechat_alert.sh
# 企业微信配置
CORPID=”wx1234567890abcdef”
CORPSECRET=”abcdef1234567890abcdef1234567890abcdef”
AGENTID=”1000001″
TOPARTY=”2″
TOUSER=”@all”
# 获取access_token
ACCESS_TOKEN=$(curl -s “https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$CORPID&corpsecret=$CORPSECRET” | jq -r “.access_token”)
# 告警信息
ALERT_TITLE=”[MySQL告警] 连接数过高”
ALERT_CONTENT=”MySQL实例:localhost:3306\n告警时间:$(date ‘+%Y-%m-%d %H:%M:%S’)\n告警级别:warning\n告警信息:连接数使用率超过80%,当前使用率:85%”
# 发送企业微信消息
curl -s -H “Content-Type: application/json” -X POST “https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$ACCESS_TOKEN” -d “{
‘touser’: ‘$TOUSER’,
‘toparty’: ‘$TOPARTY’,
‘msgtype’: ‘text’,
‘agentid’: $AGENTID,
‘text’: {
‘content’: ‘$ALERT_TITLE\n\n$ALERT_CONTENT’
},
‘safe’: 0
}”
#!/bin/bash
# mysql_dingtalk_alert.sh
# 钉钉机器人配置
WEBHOOK=”https://oapi.dingtalk.com/robot/send?access_token=abcdef1234567890abcdef1234567890abcdef”
# 告警信息
ALERT_TITLE=”[MySQL告警] 连接数过高”
ALERT_CONTENT=”MySQL实例:localhost:3306\n告警时间:$(date ‘+%Y-%m-%d %H:%M:%S’)\n告警级别:warning\n告警信息:连接数使用率超过80%,当前使用率:85%”
# 发送钉钉消息
curl -s -H “Content-Type: application/json” -X POST $WEBHOOK -d “{
‘msgtype’: ‘text’,
‘text’: {
‘content’: ‘$ALERT_TITLE\n\n$ALERT_CONTENT’
}
}”
Part04-生产案例与实战讲解
4.1 性能告警实战
使用性能告警解决MySQL性能问题的实战案例。
问题描述:收到MySQL慢查询过多告警,需要找出原因并解决
解决方法:分析慢查询日志,定位问题SQL,进行优化
# 邮件内容示例:
# 主题:[MySQL告警] warning – localhost:3306
# 内容:
# MySQL告警信息
# ====================
# 告警时间:2026-04-03 22:00:00
# 告警级别:warning
# MySQL实例:localhost:3306
# 告警信息:
# 慢查询数过多:15 (阈值:10)
# ====================
# 请及时处理!
# 2. 分析慢查询日志
# pt-query-digest /var/lib/mysql/slow.log > /tmp/slow_query_analysis.txt
# 查看分析结果
# cat /tmp/slow_query_analysis.txt | head -n 50
# 输出示例:
# # 260ms user time, 10ms system time, 24.00M rss, 214.74M vsz
# # Current date: Sat Apr 3 22:05:00 2026
# # Hostname: mysql-server
# # Files: /var/lib/mysql/slow.log
# # Overall: 15 total, 5 unique, 0.00 QPS, 0.01x concurrency ________
# # Time range: 2026-04-03T21:00:00 to 2026-04-03T22:00:00
# # Attribute total min max avg 95% stddev median
# # ============ ======= ======= ======= ======= ======= ======= =======
# # Exec time 25.36s 1.01s 2.52s 1.69s 2.45s 0.47s 1.58s
# # Lock time 0.00s 0.00s 0.00s 0.00s 0.00s 0.00s 0.00s
# # Rows sent 1.00k 10.0 10.0 10.0 10.0 0.0 10.0
# # Rows examine 10.00M 1000.0k 1000.0k 1000.0k 1000.0k 0.0 1000.0k
# # Query size 15.00B 10.0 10.0 10.0 10.0 0.0 10.0
# # Profile
# # Rank Query ID Response time Calls R/Call V/M Item
# # ==== ================== ============= ===== ====== ===== ==========
# # 1 0x1234567890ABCDEF 25.36s 100.0% 15 1.69s 0.00 SELECT fgedu_orders ORDER BY RAND()
# 3. 查看具体的慢查询SQL
# grep -A 10 “# Query_time: 1.” /var/lib/mysql/slow.log | head -n 20
# 输出示例:
# # Time: 2026-04-03T22:00:00.123456Z
# # User@Host: app_user[app_user] @ 192.168.1.100 [192.168.1.100]
# # Query_time: 1.580000 Lock_time: 0.000000 Rows_sent: 10 Rows_examined: 1000000
# use fgedudb;
# SET timestamp=1750000000;
# SELECT * FROM fgedu_orders ORDER BY RAND() LIMIT 10;
# 4. 分析SQL执行计划
mysql> EXPLAIN SELECT * FROM fgedu_orders ORDER BY RAND() LIMIT 10;
+—-+————-+————+————+——+—————+——+———+——+——–+———-+———————————+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+————+————+——+—————+——+———+——+——–+———-+———————————+
| 1 | SIMPLE | fgedu_orders| NULL | ALL | NULL | NULL | NULL | NULL | 1000000 | 100.00 | Using temporary; Using filesort |
+—-+————-+————+————+——+—————+——+———+——+——–+———-+———————————+
# 5. 优化SQL
# 原SQL:
SELECT * FROM fgedu_orders ORDER BY RAND() LIMIT 10;
# 优化后的SQL:
SELECT * FROM fgedu_orders WHERE id >= (SELECT FLOOR(MAX(id) * RAND()) FROM fgedu_orders) LIMIT 10;
# 分析优化后的执行计划
mysql> EXPLAIN SELECT * FROM fgedu_orders WHERE id >= (SELECT FLOOR(MAX(id) * RAND()) FROM fgedu_orders) LIMIT 10;
+—-+————-+————+————+——-+—————+———+———+——+——-+———-+————-+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+————+————+——-+—————+———+———+——+——-+———-+————-+
| 1 | PRIMARY | fgedu_orders| NULL | range | PRIMARY | PRIMARY | 4 | NULL | 500000 | 100.00 | Using where |
| 2 | SUBQUERY | fgedu_orders| NULL | index | NULL | PRIMARY | 4 | NULL | 1000000 | 100.00 | Using index |
+—-+————-+————+————+——-+—————+———+———+——+——-+———-+————-+
# 6. 验证优化效果
# 执行原SQL
mysql> SELECT * FROM fgedu_orders ORDER BY RAND() LIMIT 10;
# 执行时间:约1.5秒
# 执行优化后的SQL
mysql> SELECT * FROM fgedu_orders WHERE id >= (SELECT FLOOR(MAX(id) * RAND()) FROM fgedu_orders) LIMIT 10;
# 执行时间:约0.01秒
# 7. 监控告警是否恢复
# 查看慢查询数
mysql> SHOW GLOBAL STATUS LIKE ‘Slow_queries’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| Slow_queries | 15 |
+—————+——-+
# 等待一段时间后再次查看
# 5分钟后
mysql> SHOW GLOBAL STATUS LIKE ‘Slow_queries’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| Slow_queries | 15 |
+—————+——-+
# 慢查询数不再增长,说明优化有效
4.2 资源告警实战
使用资源告警解决MySQL资源问题的实战案例。
问题描述:收到MySQL数据目录磁盘空间不足告警,需要解决
解决方法:分析磁盘空间使用情况,清理不必要的文件或扩容
# 邮件内容示例:
# 主题:[MySQL告警] critical – localhost:3306
# 内容:
# MySQL告警信息
# ====================
# 告警时间:2026-04-03 22:30:00
# 告警级别:critical
# MySQL实例:localhost:3306
# 告警信息:
# 磁盘空间使用率过高:95% (目录:/var/lib/mysql/,阈值:90%)
# ====================
# 请及时处理!
# 2. 分析磁盘空间使用情况
# df -h /var/lib/mysql/
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 50G 47G 3.0G 95% /var/lib/mysql
# 3. 分析MySQL数据目录下文件大小
# du -h –max-depth=1 /var/lib/mysql/ | sort -hr
47G /var/lib/mysql/
20G /var/lib/mysql/fgedudb
15G /var/lib/mysql/mysql-bin.000001
10G /var/lib/mysql/ibdata1
2.0G /var/lib/mysql/slow.log
# 4. 分析二进制日志大小
# ls -lh /var/lib/mysql/mysql-bin.*
-rw-r—– 1 mysql mysql 15G Apr 3 22:00 /var/lib/mysql/mysql-bin.000001
-rw-r—– 1 mysql mysql 0B Apr 3 22:00 /var/lib/mysql/mysql-bin.000002
-rw-r—– 1 mysql mysql 56 Apr 3 22:00 /var/lib/mysql/mysql-bin.index
# 5. 查看二进制日志保留策略
mysql> SHOW GLOBAL VARIABLES LIKE ‘expire_logs_days’;
+——————+——-+
| Variable_name | Value |
+——————+——-+
| expire_logs_days | 0 |
+——————+——-+
# 6. 清理二进制日志
# 保留最近7天的二进制日志
mysql> PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);
Query OK, 0 rows affected (0.00 sec)
# 或者保留指定的二进制日志
mysql> PURGE BINARY LOGS TO ‘mysql-bin.000002’;
Query OK, 0 rows affected (5.00 sec)
# 7. 设置二进制日志自动清理
mysql> SET GLOBAL expire_logs_days = 7;
Query OK, 0 rows affected (0.00 sec)
# 在配置文件中永久设置
# vi /etc/my.cnf
expire_logs_days = 7
# 8. 清理慢查询日志
# 备份慢查询日志
# cp /var/lib/mysql/slow.log /var/lib/mysql/slow.log.20260403
# 清空慢查询日志
# echo “” > /var/lib/mysql/slow.log
# 或者使用MySQL命令清空
mysql> FLUSH SLOW LOGS;
Query OK, 0 rows affected (0.00 sec)
# 9. 验证磁盘空间是否释放
# df -h /var/lib/mysql/
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 50G 32G 18G 64% /var/lib/mysql
# 10. 监控告警是否恢复
# 等待告警脚本执行后,检查是否还有磁盘空间告警
# 查看告警日志
# tail -n 5 /mysql/logs/mysql_alert.log
2026-04-03 22:30:00 [MySQL告警] critical – localhost:3306 磁盘空间使用率过高:95% (目录:/var/lib/mysql/,阈值:90%)
2026-04-03 22:31:00 [MySQL告警] warning – localhost:3306 磁盘空间使用率过高:64% (目录:/var/lib/mysql/,阈值:90%)
# 磁盘空间使用率已降至阈值以下,告警级别已降为warning
4.3 连接告警实战
使用连接告警解决MySQL连接问题的实战案例。
问题描述:收到MySQL连接数过多告警,需要解决
解决方法:分析连接情况,调整连接配置或优化应用程序
# 邮件内容示例:
# 主题:[MySQL告警] critical – localhost:3306
# 内容:
# MySQL告警信息
# ====================
# 告警时间:2026-04-03 23:00:00
# 告警级别:critical
# MySQL实例:localhost:3306
# 告警信息:
# 连接数使用率过高:95% (当前:950,最大:1000)
# ====================
# 请及时处理!
# 2. 分析连接情况
mysql> SHOW GLOBAL STATUS LIKE ‘Threads_connected’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_connected | 950 |
+——————-+——-+
mysql> SHOW GLOBAL VARIABLES LIKE ‘max_connections’;
+—————–+——-+
| Variable_name | Value |
+—————–+——-+
| max_connections | 1000 |
+—————–+——-+
# 3. 分析连接状态
mysql> SELECT
Command,
COUNT(*) AS Count
FROM
information_schema.PROCESSLIST
GROUP BY
Command
ORDER BY
Count DESC;
+———+——-+
| Command | Count |
+———+——-+
| Sleep | 900 |
| Query | 45 |
| Binlog Dump | 5 |
+———+——-+
# 4. 查看连接超时设置
mysql> SHOW GLOBAL VARIABLES LIKE ‘wait_timeout’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| wait_timeout | 28800 |
+—————+——-+
mysql> SHOW GLOBAL VARIABLES LIKE ‘interactive_timeout’;
+———————+——-+
| Variable_name | Value |
+———————+——-+
| interactive_timeout | 28800 |
+———————+——-+
# 5. 解决方法
# 方法1:增加最大连接数
mysql> SET GLOBAL max_connections = 2000;
Query OK, 0 rows affected (0.00 sec)
# 在配置文件中永久修改
# vi /etc/my.cnf
max_connections = 2000
# 方法2:减少连接超时时间
mysql> SET GLOBAL wait_timeout = 7200;
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL interactive_timeout = 7200;
Query OK, 0 rows affected (0.00 sec)
# 在配置文件中永久修改
# vi /etc/my.cnf
wait_timeout = 7200
interactive_timeout = 7200
# 方法3:清理空闲连接
# 查看空闲连接
mysql> SELECT
id,
user,
host,
db,
command,
time,
state,
info
FROM
information_schema.PROCESSLIST
WHERE
command = ‘Sleep’
AND time > 3600
LIMIT 10;
# 手动杀死空闲连接
mysql> KILL 1234;
Query OK, 0 rows affected (0.00 sec)
# 或者使用脚本批量杀死空闲连接
#!/bin/bash
# kill_idle_connections.sh
MYSQL_USER=”root”
MYSQL_PASS=”password”
IDLE_TIME=3600 # 空闲时间阈值(秒)
# 获取需要杀死的连接ID
CONNECTION_IDS=$(mysql -u $MYSQL_USER -p”$MYSQL_PASS” -e “SELECT id FROM information_schema.PROCESSLIST WHERE command = ‘Sleep’ AND time > $IDLE_TIME;”)
# 杀死空闲连接
for id in $CONNECTION_IDS; do
if [ “$id” != “id” ]; then
mysql -u $MYSQL_USER -p”$MYSQL_PASS” -e “KILL $id;”
echo “Killed idle connection: $id”
fi
done
# 6. 验证连接数是否减少
# 执行清理脚本后
mysql> SHOW GLOBAL STATUS LIKE ‘Threads_connected’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_connected | 500 |
+——————-+——-+
# 7. 监控告警是否恢复
# 查看告警日志
# tail -n 5 /mysql/logs/mysql_alert.log
2026-04-03 23:00:00 [MySQL告警] critical – localhost:3306 连接数使用率过高:95% (当前:950,最大:1000)
2026-04-03 23:01:00 [MySQL告警] warning – localhost:3306 连接数使用率过高:25% (当前:500,最大:2000)
# 连接数使用率已降至阈值以下,告警级别已降为warning
4.4 安全告警实战
使用安全告警解决MySQL安全问题的实战案例。
问题描述:收到MySQL异常登录尝试告警,需要解决
解决方法:分析登录日志,定位异常登录来源,加强安全措施
# 邮件内容示例:
# 主题:[MySQL告警] warning – localhost:3306
# 内容:
# MySQL告警信息
# ====================
# 告警时间:2026-04-03 23:30:00
# 告警级别:warning
# MySQL实例:localhost:3306
# 告警信息:
# 检测到异常登录尝试:从IP 192.168.1.200尝试登录失败10次
# ====================
# 请及时处理!
# 2. 分析错误日志
# grep -i “access denied” /var/lib/mysql/mysql-error.log | tail -n 20
2026-04-03T23:29:00.123456Z 12345 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:01.123456Z 12346 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:02.123456Z 12347 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:03.123456Z 12348 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:04.123456Z 12349 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:05.123456Z 12350 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:06.123456Z 12351 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:07.123456Z 12352 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:08.123456Z 12353 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
2026-04-03T23:29:09.123456Z 12354 [Note] Access denied for user ‘root’@’192.168.1.200’ (using password: YES)
# 3. 查看当前连接
mysql> SHOW PROCESSLIST;
+—–+——+—————–+———+———+——+——-+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—–+——+—————–+———+———+——+——-+——————+
| … | … | … | … | … | … | … | … |
| 12355 | root | 192.168.1.200:54321 | NULL | Sleep | 5 | | NULL |
+—–+——+—————–+———+———+——+——-+——————+
# 4. 临时阻止异常IP
# 使用iptables临时阻止IP
# iptables -A INPUT -s 192.168.1.200 -j DROP
# 5. 加强MySQL安全措施
# 修改root用户只能本地登录
mysql> UPDATE mysql.user SET host = ‘localhost’ WHERE user = ‘root’ AND host <> ‘localhost’;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 刷新权限
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
# 禁用远程root登录
mysql> DELETE FROM mysql.user WHERE user = ‘root’ AND host = ‘%’;
Query OK, 0 rows affected (0.00 sec)
# 刷新权限
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
# 6. 启用MySQL审计日志(需要安装审计插件)
# 安装审计插件
mysql> INSTALL PLUGIN audit_log SONAME ‘audit_log.so’;
Query OK, 0 rows affected (0.00 sec)
# 启用审计日志
mysql> SET GLOBAL audit_log_policy = ‘ALL’;
Query OK, 0 rows affected (0.00 sec)
# 在配置文件中永久启用
# vi /etc/my.cnf
plugin-load=audit_log.so
audit_log_policy=ALL
# 7. 监控告警是否恢复
# 查看告警日志
# tail -n 5 /mysql/logs/mysql_alert.log
2026-04-03 23:30:00 [MySQL告警] warning – localhost:3306 检测到异常登录尝试:从IP 192.168.1.200尝试登录失败10次
# 临时阻止IP后,异常登录尝试应该会停止
Part05-风哥经验总结与分享
5.1 告警最佳实践
- 合理设置阈值:根据业务需求和历史数据,设置合理的告警阈值,避免误报和漏报
- 分级告警:根据问题的严重程度,设置不同的告警级别,确保重要告警得到及时处理
- 告警抑制:避免同一问题产生过多重复告警,减少告警噪音
- 告警升级:设计告警升级机制,确保告警能够得到及时处理
- 告警通知方式:根据告警级别和内容,选择合适的告警通知方式(邮件、短信、即时通讯工具等)
- 告警记录与分析:记录所有告警信息,定期分析告警数据,优化告警策略
- 自动化处理:对于常见问题,实现自动化处理和恢复,提高运维效率
- 定期演练:定期进行告警演练,确保告警机制的有效性和可靠性
5.2 告警优化技巧
- 减少误报:通过调整阈值、增加告警条件、设置告警延迟等方式,减少误报
- 避免漏报:通过增加监控指标、降低阈值、完善告警规则等方式,避免漏报
- 优化告警信息:告警信息应包含足够的上下文信息,便于快速定位和解决问题
- 整合告警系统:将不同来源的告警整合到同一平台,提高告警的处理效率
- 实现智能告警:利用机器学习等技术,实现告警的智能分析和预测
- 告警降噪:通过告警聚合、告警抑制、告警过滤等方式,减少告警噪音
5.3 常见问题与解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 告警误报 | 阈值设置不合理,监控数据不准确,告警条件过于简单 | 调整阈值,校准监控数据,增加告警条件 |
| 告警漏报 | 监控指标不完整,阈值设置过高,告警规则有漏洞 | 增加监控指标,降低阈值,完善告警规则 |
| 告警过多 | 阈值设置过低,告警条件过于宽松,缺乏告警抑制 | 提高阈值,收紧告警条件,实现告警抑制 |
| 告警信息不完整 | 告警模板设计不合理,缺少必要的上下文信息 | 优化告警模板,增加必要的上下文信息 |
| 告警通知不及时 | 告警系统故障,通知方式不可靠,告警接收人配置错误 | 检查告警系统,选择可靠的通知方式,核对告警接收人配置 |
| 告警处理效率低 | 告警信息不清晰,缺乏处理流程,运维人员响应不及时 | 优化告警信息,制定处理流程,加强运维人员培训 |
from MySQL:www.itpux.com
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
