Prometheus实战教程 - mysql监控

目录

Prometheus 监控 MySQL

一、架构说明

核心逻辑:MySQL 实例注册到 Consul(服务注册)→ Prometheus 配置 Consul 服务发现(自动发现 MySQL 实例)→ MySQL 暴露监控指标(via mysqld_exporter)→ Prometheus 拉取指标 → 可视化/告警。

组件角色

  • Consul:服务注册中心,存储 MySQL 服务的地址、端口、元数据(如用户名、密码)。
  • mysqld_exporter :MySQL 监控指标采集器,部署在 MySQL 节点(或独立部署),连接 MySQL 并暴露 /metrics 接口。
  • Prometheus :通过 Consul 发现所有 MySQL 实例,定期拉取 mysqld_exporter 的指标。
  • MySQL:被监控目标,需开启远程访问权限(供 exporter 连接)。

二、前置条件

  1. 已部署 Consul 集群(单节点可用于测试),确保 Prometheus 能访问 Consul 的 HTTP 接口(默认 8500 端口)。
  2. 已部署 Prometheus(2.x+ 版本),配置文件可编辑。
  3. MySQL 实例(5.7+ 或 8.0+),支持远程连接(防火墙开放 3306 端口)。
  4. 所有组件网络互通:Prometheus ↔ Consul、Prometheus ↔ mysqld_exporter、mysqld_exporter ↔ MySQL。

三、步骤 1:部署 mysqld_exporter(MySQL 指标采集)

mysqld_exporter 是 Prometheus 官方提供的 MySQL 监控采集器,需在每个 MySQL 节点(或独立节点)部署。

3.1 下载并安装 mysqld_exporter

bash 复制代码
# 下载最新版本(可替换为官网最新版本)
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.18.0/mysqld_exporter-0.18.0.linux-amd64.tar.gz

# 解压并移动到指定目录
tar xvf mysqld_exporter-0.18.0.linux-amd64.tar.gz -C /data/monitor/
cd /data/monitor/
mv mysqld_exporter-0.18.0.linux-amd64 mysqld_exporter

# 验证安装
mysqld_exporter --version  # 输出版本信息则成功

3.2 配置 MySQL 授权(供 exporter 连接)

exporter 需要连接 MySQL 采集指标,需创建专用监控用户并授权:

sql 复制代码
-- 登录 MySQL(本地或远程)
mysql -u root -p

-- 创建监控用户(允许 exporter 所在节点访问,% 表示所有地址,生产建议限制 IP)
CREATE USER 'prometheus'@'127.0.0.1' IDENTIFIED BY 'YourStrongPassword123!';

-- 授予监控所需权限(最小权限原则)
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'prometheus'@'127.0.0.1';

-- 刷新权限
FLUSH PRIVILEGES;

3.3 配置 mysqld_exporter 连接 MySQL

创建 exporter 的配置文件,存储 MySQL 连接信息:

bash 复制代码
# 创建配置文件目录
mkdir -p /data/monitor/mysqld_exporter/

# 编写配置文件(指定 MySQL 连接信息)
cat > /data/monitor/mysqld_exporter/.my.cnf << EOF
[client]
user=prometheus
password=YourStrongPassword123!
host=127.0.0.1
port=3306
EOF

# 授权(避免权限问题)
chmod 600 /data/monitor/mysqld_exporter/.my.cnf
chown root:root /data/monitor/mysqld_exporter/.my.cnf

3.4 系统服务方式启动 exporter

bash 复制代码
# 创建系统服务文件
cat > /etc/systemd/system/mysqld-exporter.service << EOF
[Unit]
Description=Prometheus MySQL Exporter
After=network.target

[Service]
User=root
Group=root
ExecStart=/data/monitor/mysqld_exporter/mysqld_exporter --config.my-cnf=/data/monitor/mysqld_exporter/.my.cnf --web.listen-address=:9104
Restart=always

[Install]
WantedBy=multi-user.target
EOF

# 重载服务配置、启动并设置开机自启
systemctl daemon-reload
systemctl start mysqld-exporter
systemctl enable mysqld-exporter

# 验证启动状态(默认暴露 9104 端口)
systemctl status mysqld-exporter
curl http://[IP]:9104/metrics  # 能看到指标则成功

四、步骤 2:MySQL 服务注册到 Consul

Consul 支持服务注册(手动注册/自动注册),这里提供两种方式(推荐手动注册用于测试,生产可结合 Consul Agent 自动注册)。

方式 1:手动注册(通过 Consul HTTP API)

适合临时测试或少量实例,无需在 MySQL 节点部署 Consul Agent:

bash 复制代码
# 向 Consul 注册 MySQL 服务(替换以下参数)
# Consul 地址:192.168.37.40:8500(Consul Server 或 Client 的 HTTP 端口)
# 服务名称:mysqld-exporter(Prometheus 后续通过该名称发现)
# 服务地址:192.168.37.21(MySQL 节点 IP,即 mysqld_exporter 所在 IP)
# 服务端口:9104(mysqld_exporter 暴露的端口)
# 元数据(可选):可存储 MySQL 实例名称、环境等,供 Prometheus 筛选

curl http://192.168.37.40:8500/v1/agent/service/register -X PUT -i -H "Content-Type:application/json" -H "X-Consul-Token: f5cc7d96-ba0f-0501-4252-903e059514bb" -d '{
  "ID": "mysql-192.168.37.21:3306",  
  "Name": "mysqld-exporter",
  "Tags": [
    "mysqld-exporter",
    "dev"
  ],
  "Address": "192.168.37.21",
  "Port": 9104,
  "EnableTagOverride": false,
  "Check": {
    "DeregisterCriticalServiceAfter": "90m",
    "HTTP": "http://192.168.37.21:9104/metrics",
    "Interval": "10s",
    "timeout": "2s"
  }
}'

方式 2:自动注册(通过 Consul Agent)

适合生产环境(多实例、动态扩容),需在每个 MySQL 节点部署 Consul Agent(作为 Client 加入 Consul 集群):

  1. 部署 Consul Agent(参考 Consul 官方文档),确保 Agent 已加入集群。
  2. 创建服务注册配置文件
bash 复制代码
# 在 MySQL 节点(Consul Agent 所在节点)创建服务配置
mkdir -p /etc/consul.d
cat > /etc/consul.d/mysql-monitor.json << EOF
{
  "service": {
    "id": "mysql-$(hostname -i):9104",  # 自动获取 IP 作为唯一 ID
    "name": "mysql-monitor",  # 服务名称(与手动注册一致)
    "port": 9104,
    "tags": ["env=prod", "instance=mysql-slave"],
    "meta": {
      "mysql_host": "$(hostname -i)",
      "mysql_port": 3306
    },
    "checks": [  # 健康检查(可选,Consul 定期检测 exporter 是否存活)
      {
        "http": "http://$(hostname -i):9104/metrics",
        "interval": "10s",
        "timeout": "3s"
      }
    ]
  }
}
EOF
  1. 重启 Consul Agent 加载配置:
bash 复制代码
systemctl restart consul

验证服务注册结果

访问 Consul UI(默认 http://Consul-IP:8500/ui),在「Services」中查看 mysql-monitor 服务,状态为「Healthy」则注册成功。

五、步骤 3:Prometheus 配置 Consul 服务发现

修改 Prometheus 配置文件,添加 Consul 服务发现规则,让 Prometheus 自动发现所有注册到 Consul 的 mysql-monitor 服务。

5.1 编辑 Prometheus 配置文件(prometheus.yml)

yaml 复制代码
global:
  scrape_interval: 15s  # 全局拉取间隔

scrape_configs:
  # 其他已有配置(如 node_exporter)...

  # 添加 MySQL 监控的 Consul 服务发现配置
  - job_name: 'mysqld-exporter'  # 任务名称(自定义)
    consul_sd_configs:
      - server: '192.168.37.40:8500'  # Consul 的 HTTP 地址(Server 或 Client)
        datacenter: 'dc1'  # 与 Consul 注册时的 datacenter 一致
        tag_separator: ','
        scheme: 'http'
        services: ['mysqld-exporter']  # 只发现 Consul 中名称为 mysql-monitor 的服务
        # 可选:过滤标签(只发现 tags 包含 env=prod 的服务)
        # filter: 'ServiceTags contains "env=prod"'

    # 可选:重写拉取路径(默认 /metrics,exporter 无需修改则无需配置)
    metrics_path: '/metrics'

    # 可选:添加标签(用于区分环境、实例)
    relabel_configs:
      # 从 Consul 服务的 meta 中提取 mysql_host 作为标签
      - source_labels: [__meta_consul_service_meta_mysql_host]
        target_label: mysql_host
      # 从 Consul 服务的 tags 中提取 env 作为标签
      - source_labels: [__meta_consul_service_tag_env]
        target_label: env
      # 从 Consul 服务的 ID 中提取实例信息
      - source_labels: [__meta_consul_service_id]
        target_label: instance

5.2 验证 Prometheus 配置并重启

bash 复制代码
# 验证配置文件语法是否正确
promtool check config /etc/prometheus/prometheus.yml

# 重启 Prometheus 加载配置
systemctl restart prometheus

5.3 确认服务发现结果

访问 Prometheus UI(默认 http://Prometheus-IP:9090):

  1. 进入「Status → Targets」,查看 mysql-monitor 任务。
  2. 若所有 MySQL 实例的 State 为「UP」,说明服务发现成功,Prometheus 已开始拉取指标。

六、步骤 4:可视化监控(Grafana)

Prometheus 本身不擅长可视化,推荐使用 Grafana 导入 MySQL 监控面板。

4.1 导入 MySQL 监控面板

  1. 登录 Grafana(已集成 Prometheus 数据源)。
  2. 进入「Dashboards → Import」,输入 MySQL 官方面板 ID:7362(或搜索「MySQL by Prometheus & mysqld_exporter」)。
  3. 选择 Prometheus 数据源,点击「Import」,即可看到完整的 MySQL 监控面板(包含连接数、QPS、慢查询、表空间、索引命中率等指标)。

七、Mysql监控指标

MySQL 核心监控指标清单(按维度分类)

一、可用性指标(基础必监控)
指标名 指标含义 核心 PromQL 查询 监控意义
mysql_up MySQL 实例是否在线 mysql_up 直接判断实例是否存活(1=在线,0=离线)
mysql_global_status_uptime 实例运行时长(秒) mysql_global_status_uptime 检测实例是否频繁重启(数值骤降)
二、连接数指标(避免连接耗尽)
指标名 指标含义 核心 PromQL 查询 监控意义
mysql_global_status_connections 当前已建立的连接数 mysql_global_status_connections 实时查看连接数变化
mysql_global_variables_max_connections 最大允许连接数 mysql_global_variables_max_connections 配置基准值
- 连接数使用率 mysql_global_status_connections / mysql_global_variables_max_connections 核心:超过80%需告警
mysql_global_status_aborted_connects 失败的连接尝试数 increase(mysql_global_status_aborted_connects[5m]) 检测密码错误、权限问题等连接失败
三、性能指标(定位慢查询/锁/临时表问题)
指标名 指标含义 核心 PromQL 查询 监控意义
mysql_global_status_slow_queries 慢查询总数 increase(mysql_global_status_slow_queries[5m]) 慢查询突增→SQL 性能问题
mysql_global_status_table_locks_waited 表锁等待次数 increase(mysql_global_status_table_locks_waited[5m]) 锁等待频繁→长事务/慢 SQL
mysql_global_status_created_tmp_tables 临时表创建总数 increase(mysql_global_status_created_tmp_tables[5m]) 临时表过多→SQL 未优化
mysql_global_status_created_tmp_disk_tables 磁盘临时表创建数 increase(mysql_global_status_created_tmp_disk_tables[5m]) / increase(mysql_global_status_created_tmp_tables[5m]) 占比超20%→需调优 tmp_table_size
mysql_global_status_handler_read_rnd 随机读次数 rate(mysql_global_status_handler_read_rnd[1m]) 数值过高→缺少索引
四、流量指标(QPS/TPS/网络吞吐)
指标名 指标含义 核心 PromQL 查询 监控意义
mysql_global_status_queries 总查询数 rate(mysql_global_status_queries[1m]) 计算 QPS(每秒查询数)→流量波动
mysql_global_status_handler_commit 事务提交数 rate(mysql_global_status_handler_commit[1m]) - rate(mysql_global_status_handler_rollback[1m]) 计算 TPS(每秒事务数)→写入负载
mysql_global_status_bytes_received 网络流入字节总数 rate(mysql_global_status_bytes_received[1m]) 流入流量→数据写入/攻击检测
mysql_global_status_bytes_sent 网络流出字节总数 rate(mysql_global_status_bytes_sent[1m]) 流出流量→数据查询/泄露检测
五、存储指标(磁盘/空间)
指标名 指标含义 核心 PromQL 查询 监控意义
mysql_disk_used_bytes 数据目录已用磁盘空间 mysql_disk_used_bytes 实时查看磁盘使用量
mysql_disk_total_bytes 数据目录总磁盘空间 mysql_disk_used_bytes / mysql_disk_total_bytes 使用率超85%→需扩容/清理
mysql_global_status_disk_full 磁盘满错误数 increase(mysql_global_status_disk_full[5m]) 检测磁盘满导致的写失败
六、主从复制指标(同步状态)
指标名 指标含义 核心 PromQL 查询 监控意义
mysql_slave_seconds_behind_master 从库延迟秒数 mysql_slave_seconds_behind_master 延迟超60秒→同步异常
mysql_slave_io_running IO 线程是否运行 mysql_slave_io_running (1=运行,0=停止) IO 线程停止→同步中断
mysql_slave_sql_running SQL 线程是否运行 mysql_slave_sql_running (1=运行,0=停止) SQL 线程停止→数据同步失败

八、告警

告警规则

yaml 复制代码
groups:
- name: mysql_alerts
  rules:
  # ========== 基础可用性告警 ==========
  # 1. MySQL 服务不可用
  - alert: MySQLDown
    expr: mysql_up == 0
    for: 30s
    labels:
      severity: critical
      service: mysql
    annotations:
      summary: "MySQL 服务不可用 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 已下线超过 30 秒,请检查服务状态。"

  # 2. MySQL 连接数过高
  - alert: MySQLTooManyConnections
    expr: mysql_global_status_connections / mysql_global_variables_max_connections > 0.8
    for: 2m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL 连接数过高 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 连接数使用率超过 80% (当前: {{ $value | humanizePercentage }}),请检查是否有连接泄露或业务突增。"

  # 3. MySQL 慢查询数突增
  - alert: MySQLSlowQueriesIncreasing
    expr: increase(mysql_global_status_slow_queries[5m]) > 10
    for: 5m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL 慢查询数突增 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 最近 5 分钟慢查询数增加了 {{ $value }} 个,需检查慢查询日志优化 SQL。"

  # 4. MySQL 磁盘使用率过高(数据目录)
  - alert: MySQLDiskUsageHigh
    expr: mysql_disk_used_bytes / mysql_disk_total_bytes > 0.85
    for: 5m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL 磁盘使用率过高 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 数据目录磁盘使用率超过 85% (当前: {{ $value | humanizePercentage }}),请清理数据或扩容磁盘。"

  # 5. MySQL 主从复制延迟
  - alert: MySQLReplicationLag
    expr: mysql_slave_seconds_behind_master > 60
    for: 2m
    labels:
      severity: critical
      service: mysql
    annotations:
      summary: "MySQL 主从复制延迟 ({{ $labels.instance }})"
      description: "MySQL 从库 {{ $labels.instance }} 复制延迟超过 60 秒 (当前: {{ $value }} 秒),请检查主从同步状态。"

  # 6. MySQL 表锁等待时间过长
  - alert: MySQLTableLockWaits
    expr: mysql_global_status_table_locks_waited > 0 and increase(mysql_global_status_table_locks_waited[5m]) > 10
    for: 1m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL 表锁等待频繁 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 最近 5 分钟表锁等待数增加 {{ $value }} 次,可能存在长事务或慢 SQL。"

  # 7. MySQL 临时表创建过多(磁盘临时表)
  - alert: MySQLTempTablesOnDisk
    expr: increase(mysql_global_status_created_tmp_disk_tables[5m]) / increase(mysql_global_status_created_tmp_tables[5m]) > 0.2
    for: 5m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL 磁盘临时表占比过高 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 磁盘临时表占比超过 20% (当前: {{ $value | humanizePercentage }}),需优化 SQL 或调整 tmp_table_size 配置。"

  # ========== 流量相关告警(修正核心指标名) ==========
  # 8. MySQL 每秒查询量(QPS)突增
  - alert: MySQLQPSHigh
    expr: rate(mysql_global_status_queries[1m]) > 5000  # 标准指标名:mysql_global_status_queries
    for: 2m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL QPS 突增 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 每秒查询量超过 5000 (当前: {{ $value | humanize }}),可能存在流量洪峰或异常查询。"

  # 9. MySQL 每秒查询量(QPS)突降
  - alert: MySQLQPSLow
    expr: rate(mysql_global_status_queries[1m]) < 100  # 标准指标名:mysql_global_status_queries
    for: 5m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL QPS 突降 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 每秒查询量低于 100 (当前: {{ $value | humanize }}),可能存在业务中断或采集异常。"

  # 10. MySQL 网络流入流量过高
  - alert: MySQLNetworkInHigh
    expr: rate(mysql_global_status_bytes_received[1m]) > 10485760  # 10MB/s,标准指标名
    for: 3m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL 流入流量过高 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 每秒流入流量超过 10MB (当前: {{ $value | humanizeBytes }}/s),可能存在大量数据写入或网络攻击。"

  # 11. MySQL 网络流出流量过高
  - alert: MySQLNetworkOutHigh
    expr: rate(mysql_global_status_bytes_sent[1m]) > 10485760  # 10MB/s,标准指标名
    for: 3m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL 流出流量过高 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 每秒流出流量超过 10MB (当前: {{ $value | humanizeBytes }}/s),可能存在大量数据查询或数据泄露风险。"

  # 12. MySQL 每秒写入量(TPS)突增
  - alert: MySQLTPSHigh
    expr: rate(mysql_global_status_handler_commit[1m]) - rate(mysql_global_status_handler_rollback[1m]) > 1000  # 标准指标名
    for: 2m
    labels:
      severity: warning
      service: mysql
    annotations:
      summary: "MySQL TPS 突增 ({{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 每秒事务数超过 1000 (当前: {{ $value | humanize }}),可能存在批量写入或业务峰值。"

压测和告警

关于Mysql压测,之前写过一个文章
MySQL 压测实战:sysbench 从入门到精通

关于告警配置(钉钉)
告警通知实现 - 邮件 + 钉钉 + 自定义告警模板

相关推荐
wsx_iot6 小时前
mysql的快照读和当前读
数据库·mysql
梁萌6 小时前
MySQL分区表使用保姆级教程
数据库·mysql·优化·分区表·分区·partitions
Logic1017 小时前
《数据库运维》 郭文明 实验4 数据库备份与恢复实验核心操作与思路解析
运维·数据库·sql·mysql·学习笔记·形考作业·国家开放大学
hssfscv7 小时前
Mysql学习笔记——多表查询
笔记·学习·mysql
MC皮蛋侠客8 小时前
MySQL数据库迁移脚本及使用说明
数据库·mysql
soft20015258 小时前
《Rocky Linux 9.6 部署 MySQL 8.0 生产手册(含错误处理)》
linux·mysql·adb
帝吃藕和8 小时前
MySQL 知识点复习- 6. inner/right/left join
mysql
你真的可爱呀9 小时前
3.MySQL 数据库集成
mysql·node.js·express
Logic10110 小时前
《数据库运维》 郭文明 实验5 数据库性能监视与优化实验核心操作与思路解析
运维·数据库·sql·mysql·计算机网络技术·形考作业·国家开放大学