Skip to content

MySQL 告警策略与故障分级

告警策略概述

告警的重要性

MySQL 告警是数据库运维的重要组成部分,能够帮助运维人员及时发现和解决问题,避免或减少业务损失。有效的告警策略可以:

  • 提前发现潜在问题
  • 减少故障定位时间
  • 确保数据库服务可用性
  • 降低运维成本
  • 提高系统可靠性

告警设计原则

原则描述
及时性告警必须及时,以便快速响应
准确性减少误报和漏报
分级告警根据问题影响程度分级
可操作告警信息必须包含可操作的信息
告警抑制避免重复告警和告警风暴
告警升级长时间未处理的告警自动升级
多渠道通知确保告警能够送达相关人员

故障分级

分级标准

根据故障的影响范围、严重程度和恢复时间要求,MySQL 故障通常分为以下几个级别:

级别名称描述示例恢复时间要求
P1紧急数据库完全不可用,业务完全中断- MySQL 服务停止
- 主从复制完全中断
- 数据丢失
立即响应(< 5 分钟)
P2高优先级数据库性能严重下降,部分业务受影响- 连接数接近上限
- 慢查询突增
- 主从延迟大
15 分钟内响应
P3中优先级数据库存在隐患,可能影响性能- 磁盘空间不足
- 缓存命中率下降
- 锁等待增加
1 小时内响应
P4低优先级数据库存在可优化项- 索引使用率低
- 配置不合理
- 慢查询少量增加
24 小时内响应

分级管理

响应流程

级别响应流程
P11. 立即通知所有 DBA 成员
2. 10 分钟内开始处理
3. 每 15 分钟更新一次状态
4. 2 小时内提供初步分析
5. 恢复后进行详细复盘
P21. 通知值班 DBA
2. 30 分钟内开始处理
3. 每 30 分钟更新一次状态
4. 4 小时内提供分析报告
P31. 通知相关 DBA
2. 1 小时内开始处理
3. 24 小时内解决
P41. 记录问题
2. 安排在维护窗口解决

通知方式

级别通知方式通知频率
P1- 短信
- 电话
- 即时通讯工具
- 邮件
立即发送,未确认则 5 分钟后重发
P2- 短信
- 即时通讯工具
- 邮件
立即发送,未确认则 15 分钟后重发
P3- 即时通讯工具
- 邮件
立即发送
P4- 邮件每日汇总发送

告警指标与阈值

可用性告警

版本差异

指标MySQL 5.6MySQL 5.7MySQL 8.0
MGR 集群状态
GTID 复制状态⚠️ 实验性
事务锁监控基础增强全面
指标描述监控命令告警阈值级别
MySQL 服务状态MySQL 进程是否运行systemctl status mysqldSHOW GLOBAL STATUS LIKE 'Uptime';服务停止P1
主从复制状态复制 IO/SQL 线程状态SHOW SLAVE STATUS\GSlave_IO_Running 或 Slave_SQL_Running 为 NoP1
MGR 集群状态MGR 成员状态SELECT * FROM performance_schema.replication_group_members;有成员状态非 ONLINEP1

连接告警

指标描述监控命令告警阈值级别
当前连接数当前活跃的连接数SHOW GLOBAL STATUS LIKE 'Threads_connected';超过 max_connections 的 80%P2
连接错误数连接失败的次数SHOW GLOBAL STATUS LIKE 'Connection_errors_%';每分钟 > 5 次P3
拒绝连接数因连接数满而拒绝的连接SHOW GLOBAL STATUS LIKE 'Threads_rejected';任何非零值P2

性能告警

指标描述监控命令告警阈值级别
慢查询数慢查询的数量SHOW GLOBAL STATUS LIKE 'Slow_queries';每分钟 > 10 次P2
活跃线程数正在执行查询的线程数SHOW GLOBAL STATUS LIKE 'Threads_running';超过 CPU 核心数 * 2P2
锁等待时间锁等待的总时间SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_time';每分钟 > 1000msP3
死锁次数发生死锁的次数SHOW GLOBAL STATUS LIKE 'Innodb_deadlocks';任何非零值P3

资源告警

指标描述监控命令告警阈值级别
磁盘空间使用率数据目录磁盘使用率df -h> 80%P3
内存使用率MySQL 内存使用情况SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_%';缓冲池命中率 < 95%P3
CPU 使用率MySQL 进程 CPU 使用率top -p $(pidof mysqld)持续 > 80%P2
临时表使用率磁盘临时表占比SHOW GLOBAL STATUS LIKE 'Created_tmp%tables';Created_tmp_disk_tables / Created_tmp_tables > 10%P3

日志告警

指标描述监控命令告警阈值级别
错误日志错误日志中的错误信息grep -i error /var/log/mysqld.log出现 ERROR 级别日志P2
二进制日志大小二进制日志文件大小SHOW BINARY LOGS;单个文件 > 1GP4
慢查询日志增长慢查询日志增长速度du -sh /var/log/mysql-slow.log每日增长 > 1GP3

复制告警

指标描述监控命令告警阈值级别
主从延迟从库延迟主库的秒数SHOW SLAVE STATUS\G(Seconds_Behind_Master)> 30 秒P2
复制队列大小中继日志队列大小SHOW GLOBAL STATUS LIKE 'Slave_queue_length';> 1000P3
复制错误复制过程中的错误SHOW SLAVE STATUS\G(Last_IO_Error, Last_SQL_Error)任何错误信息P1

告警配置示例

Prometheus + Alertmanager 告警规则

配置 Prometheus 告警规则

编辑 mysql_alerts.yml

yaml
groups:
- name: mysql_alerts
  rules:
    # 1. 可用性告警
    - alert: MySQLDown
      expr: mysql_up == 0
      for: 30s
      labels:
        severity: critical
        level: P1
      annotations:
        summary: MySQL 服务不可用
        description: MySQL 实例 {{ $labels.instance }} 已停止运行超过 30 秒

    - alert: MySQLReplicationBroken
      expr: mysql_slave_status_slave_sql_running != 1 or mysql_slave_status_slave_io_running != 1
      for: 30s
      labels:
        severity: critical
        level: P1
      annotations:
        summary: MySQL 复制中断
        description: MySQL 实例 {{ $labels.instance }} 的复制已中断

    # 2. 连接告警
    - alert: MySQLHighConnectionUsage
      expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100 > 80
      for: 1m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: MySQL 连接使用率高
        description: MySQL 实例 {{ $labels.instance }} 连接使用率达到 {{ $value | printf "%.2f" }}%

    - alert: MySQLRejectedConnections
      expr: rate(mysql_global_status_threads_rejected[5m]) > 0
      for: 1m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: MySQL 连接被拒绝
        description: MySQL 实例 {{ $labels.instance }} 拒绝了 {{ $value }} 个连接

    # 3. 性能告警
    - alert: MySQLHighSlowQueries
      expr: rate(mysql_global_status_slow_queries[5m]) > 10
      for: 1m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: MySQL 慢查询数高
        description: MySQL 实例 {{ $labels.instance }} 每秒慢查询数达到 {{ $value }}

    - alert: MySQLInnoDBDeadlocks
      expr: rate(mysql_global_status_innodb_deadlocks[5m]) > 0
      for: 1m
      labels:
        severity: warning
        level: P3
      annotations:
        summary: MySQL 发生死锁
        description: MySQL 实例 {{ $labels.instance }} 每秒发生 {{ $value }} 次死锁

    # 4. 资源告警
    - alert: MySQLDiskSpaceLow
      expr: mysql_global_variables_innodb_data_file_path != '' and (mysql_global_status_innodb_data_fsyncs / mysql_global_status_innodb_data_writes) > 0.9
      for: 10m
      labels:
        severity: warning
        level: P3
      annotations:
        summary: MySQL 磁盘空间不足
        description: MySQL 实例 {{ $labels.instance }} 磁盘空间使用率高

    - alert: MySQLBufferPoolHitRateLow
      expr: (1 - (mysql_global_status_innodb_buffer_pool_reads / mysql_global_status_innodb_buffer_pool_read_requests)) * 100 < 95
      for: 5m
      labels:
        severity: warning
        level: P3
      annotations:
        summary: MySQL 缓冲池命中率低
        description: MySQL 实例 {{ $labels.instance }} 缓冲池命中率为 {{ $value | printf "%.2f" }}%

    # 5. 复制告警
    - alert: MySQLReplicationLag
      expr: mysql_slave_status_seconds_behind_master > 30
      for: 1m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: MySQL 复制延迟大
        description: MySQL 实例 {{ $labels.instance }} 复制延迟达到 {{ $value }} 秒

配置 Alertmanager

编辑 alertmanager.yml

yaml
global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'prometheus@example.com'
  smtp_auth_username: 'prometheus'
  smtp_auth_password: 'SmtpPassword1!'

route:
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 1h
  receiver: 'team-dba'
  routes:
    - match:
        level: P1
      receiver: 'team-dba-p1'
      repeat_interval: 5m
    - match:
        level: P2
      receiver: 'team-dba-p2'
      repeat_interval: 15m

receivers:
- name: 'team-dba'
  email_configs:
    - to: 'dba@example.com'
      send_resolved: true
  webhook_configs:
    - url: 'https://hooks.example.com/alertmanager'

- name: 'team-dba-p1'
  email_configs:
    - to: 'dba@example.com'
      send_resolved: true
  pagerduty_configs:
    - service_key: 'pagerduty-p1-key'
      send_resolved: true
  webhook_configs:
    - url: 'https://hooks.example.com/alertmanager-p1'

- name: 'team-dba-p2'
  email_configs:
    - to: 'dba@example.com'
      send_resolved: true
  webhook_configs:
    - url: 'https://hooks.example.com/alertmanager-p2'

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'cluster', 'service']

Zabbix 告警配置

创建告警媒介

  1. 进入 Zabbix Web 界面,选择 "Administration" > "Media types"
  2. 点击 "Create media type"
  3. 选择类型(如 Email、SMS 等)
  4. 配置相关参数
  5. 点击 "Update"

配置用户告警媒介

  1. 选择 "Administration" > "Users"
  2. 选择用户,点击 "Media"
  3. 点击 "Add"
  4. 选择媒介类型,配置收件人
  5. 点击 "Add"
  6. 点击 "Update"

创建触发器

  1. 选择 "Configuration" > "Hosts"
  2. 选择主机,点击 "Triggers"
  3. 点击 "Create trigger"
  4. 配置触发器名称、表达式、优先级等
  5. 点击 "Add"

示例触发器表达式

  • MySQL 服务停止:{MySQL:mysql.ping.nodata(30s)}=1(P1)
  • 连接数高:{MySQL:mysql.status[Threads_connected].last()}/{MySQL:mysql.variables[max_connections].last()}*100>80(P2)
  • 慢查询多:{MySQL:mysql.status[Slow_queries].delta(5m)}>50(P2)
  • 主从延迟大:{MySQL:mysql.slave_status[Seconds_Behind_Master].last()}>30(P2)

告警最佳实践

告警信息设计

告警信息应包含以下关键信息:

  1. 告警级别:P1/P2/P3/P4
  2. 告警名称:清晰描述问题
  3. 告警时间:精确到秒
  4. 告警对象:具体的 MySQL 实例
  5. 告警指标:触发告警的指标
  6. 当前值:指标的当前值
  7. 阈值:告警阈值
  8. 告警描述:详细描述问题
  9. 可能原因:可能的故障原因
  10. 建议操作:建议的处理步骤

示例告警信息

[P2 告警] MySQL 连接使用率高
时间:2023-10-05 14:30:00
实例:192.168.1.101:3306
指标:Threads_connected
当前值:1600
阈值:> 1600(max_connections 的 80%)
描述:MySQL 实例 192.168.1.101:3306 的连接使用率达到 80%,可能影响新连接建立
可能原因:1. 应用连接数增加 2. 连接泄漏 3. 长连接未释放
建议操作:1. 检查应用连接池配置 2. 查看慢查询日志 3. 考虑增加 max_connections

告警抑制

告警抑制可以避免告警风暴,提高告警的有效性:

  1. 同类型告警抑制:同一类型的告警只发送一次
  2. 父子关系抑制:父告警触发时,抑制子告警
  3. 时间抑制:短时间内相同告警只发送一次
  4. 告警聚合:将多个相关告警聚合为一个

告警升级

告警升级确保问题能够得到及时处理:

级别初始通知第一次升级第二次升级
P1短信 + 邮件 + 即时通讯5 分钟未确认,电话通知15 分钟未解决,升级到上级领导
P2短信 + 邮件 + 即时通讯30 分钟未确认,电话通知1 小时未解决,升级到上级领导
P3邮件 + 即时通讯2 小时未确认,短信通知4 小时未解决,电话通知
P4邮件1 天未处理,短信通知3 天未处理,升级到上级领导

告警统计与分析

定期对告警进行统计和分析,可以优化告警策略:

  1. 告警数量统计:按级别、类型、时间段统计
  2. 告警触发原因分析:找出常见问题
  3. 告警处理时间统计:评估运维效率
  4. 误报率分析:优化告警阈值
  5. 告警抑制效果分析:调整抑制规则

示例告警统计报告

月份P1 告警P2 告警P3 告警P4 告警误报率平均处理时间
1 月215451205%30 分钟
2 月112381103%25 分钟
3 月0832952%20 分钟

故障处理流程

故障处理步骤

  1. 告警接收:通过多种渠道接收告警
  2. 告警确认:确认告警真实性,避免误报
  3. 故障定位:使用监控工具定位问题
  4. 故障处理:根据故障类型采取相应措施
  5. 故障验证:验证故障是否解决
  6. 告警关闭:关闭已解决的告警
  7. 故障复盘:分析故障原因,提出改进措施

常见故障处理方法

故障类型处理方法
MySQL 服务停止1. 查看错误日志
2. 检查磁盘空间
3. 检查内存使用
4. 重启服务
复制中断1. 查看复制错误
2. 根据错误类型修复
3. 重启复制
连接数满1. 查看慢查询
2. 检查连接泄漏
3. 临时增加 max_connections
4. 优化查询
慢查询突增1. 查看慢查询日志
2. 分析执行计划
3. 优化索引或查询
4. 考虑读写分离
主从延迟大1. 检查从库性能
2. 优化复制配置
3. 考虑并行复制
4. 增加从库资源

总结

MySQL 告警策略和故障分级是数据库运维的重要组成部分,通过合理的告警设计和故障分级,可以提高数据库的可用性和可靠性,减少业务损失。

在实际运维中,应根据业务需求和系统规模,不断优化告警策略,提高告警的准确性和有效性。同时,定期进行故障演练和复盘,提高运维团队的应急处理能力。

通过本文的介绍,您应该掌握了 MySQL 告警策略的设计原则、故障分级方法、告警配置示例和最佳实践,能够根据实际需求设计和实施有效的告警策略。