MySQL 监控
1. 概述
MySQL 监控是数据库运维的重要组成部分,通过监控数据库连接、SQL 执行、慢查询等指标,可以及时发现和解决数据库性能问题,保证系统稳定运行。在梵医云系统中,使用 Druid 连接池进行 MySQL 监控。Druid 是阿里巴巴开源的数据库连接池,提供了强大的监控功能。本文档介绍如何配置和使用 MySQL 监控。
2. 监控体系架构
2.1 监控组件
梵医云系统 MySQL 监控包含以下组件:
- Druid 连接池:数据库连接池和监控组件
- Druid StatViewServlet:监控页面 Servlet
- Druid WebStatFilter:Web 应用监控过滤器
- Prometheus Exporter:指标导出到 Prometheus(可选)
2.2 监控架构
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Application │ ───> │ Druid Pool │ ───> │ MySQL DB │
│ │ │ Monitor │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ Druid Web │
│ Monitor │
└─────────────┘3. Druid 配置
3.1 添加依赖
在 pom.xml 中添加 Druid 依赖:
xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.23</version>
</dependency>3.2 配置 Druid
编辑 application.yaml:
yaml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.1.10:3306/fanyi_cloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: your_password
druid:
# 连接池初始化大小
initial-size: 5
# 连接池最小空闲连接数
min-idle: 10
# 连接池最大活跃连接数
max-active: 20
# 获取连接等待超时时间(毫秒)
max-wait: 60000
# 配置间隔多久进行一次检测,检测需要关闭的空闲连接(毫秒)
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间(毫秒)
min-evictable-idle-time-millis: 300000
# 配置一个连接在池中最大生存的时间(毫秒)
max-evictable-idle-time-millis: 900000
# 配置检测连接是否有效的 SQL
validation-query: SELECT 1
# 申请连接时执行 validationQuery 检测连接是否有效
test-while-idle: true
# 申请连接时执行 validationQuery 检测连接是否有效
test-on-borrow: false
# 归还连接时执行 validationQuery 检测连接是否有效
test-on-return: false
# 是否缓存 preparedStatement
pool-prepared-statements: true
# 配置监控统计拦截的 filters
filters: stat,wall,slf4j
# 通过 connectProperties 属性来打开 mergeSql 功能;慢 SQL 记录
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# StatViewServlet 配置
stat-view-servlet:
# 是否启用 StatViewServlet(监控页面)
enabled: true
# 访问路径
url-pattern: /druid/*
# 登录用户名
login-username: admin
# 登录密码
login-password: admin
# 允许访问的 IP 地址(空表示允许所有)
allow: ""
# 拒绝访问的 IP 地址
deny: ""
# 是否禁用重置按钮
reset-enable: true
# WebStatFilter 配置
web-stat-filter:
# 是否启用 WebStatFilter
enabled: true
# 拦截路径
url-pattern: /*
# 排除路径
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
# session 统计最大数量
session-stat-max-count: 1000
# 是否启用 session 统计
session-stat-enable: true
# principalSessionName 配置
principal-session-name: username
# profileEnable 配置
profile-enable: true
# 配置 StatFilter
filter:
stat:
# 是否启用 StatFilter
enabled: true
# 慢 SQL 记录(毫秒)
log-slow-sql: true
slow-sql-millis: 5000
# 合并 SQL
merge-sql: true
wall:
# 是否启用 WallFilter(防火墙)
enabled: true
# 配置允许的 SQL 语句
config:
multi-statement-allow: true
slf4j:
# 是否启用 Slf4jFilter
enabled: true
# 是否开启日志
statement-log-enabled: true
# 是否开启结果集日志
result-set-log-enabled: true
# 是否开启连接日志
connection-log-enabled: true3.3 配置安全访问
编辑 SecurityConfiguration.java,允许访问 Druid 监控页面:
java
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/druid/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}4. 访问监控页面
4.1 访问 Druid 监控页面
启动应用后,在浏览器中访问:
http://your-server-ip:48080/druid输入用户名和密码(默认:admin/admin)登录。
4.2 监控页面功能
Druid 监控页面包含以下功能:
- 数据源:查看数据源信息、连接池状态
- SQL 监控:查看 SQL 执行情况、慢查询
- SQL 防火墙:查看 SQL 防火墙拦截情况
- Web 应用:查看 Web 应用请求统计
- URI 监控:查看 URI 访问统计
- Session 监控:查看 Session 统计信息
- Spring 监控:查看 Spring Bean 方法调用统计
5. 监控指标说明
5.1 数据源监控
连接池信息:
initial-size:初始连接数min-idle:最小空闲连接数max-active:最大活跃连接数current-active:当前活跃连接数current-idle:当前空闲连接数max-wait:获取连接最大等待时间
连接使用情况:
activeCount:活跃连接数activePeak:活跃连接峰值activePeakTime:活跃连接峰值时间poolingCount:池中连接数poolingPeak:池中连接峰值poolingPeakTime:池中连接峰值时间
连接等待情况:
waitThreadCount:等待线程数notEmptyWaitCount:等待连接次数notEmptyWaitNanos:等待连接总时间notEmptyWaitPeak:等待连接峰值notEmptyWaitPeakTime:等待连接峰值时间
5.2 SQL 监控
SQL 执行统计:
executeCount:执行次数executeMillisTotal:执行总时间executeMillisMax:执行最大时间executeMillisMin:执行最小时间executeMillisAvg:执行平均时间executeErrorCount:执行错误次数executeErrorLast:最后执行错误时间
SQL 事务统计:
commitCount:提交次数rollbackCount:回滚次数fetchRowCount:获取行数updateCount:更新行数
SQL 慢查询:
slowSqlMillis:慢 SQL 阈值(毫秒)slowSqlCount:慢 SQL 次数slowSqlMillisMax:慢 SQL 最大执行时间
5.3 Web 应用监控
请求统计:
RequestCount:请求总数RequestTimeMillisTotal:请求总时间RequestTimeMillisMax:请求最大时间RequestTimeMillisMin:请求最小时间RequestTimeMillisAvg:请求平均时间
JDBC 统计:
JdbcExecuteCount:JDBC 执行次数JdbcExecuteTimeMillis:JDBC 执行时间JdbcCommitCount:JDBC 提交次数JdbcRollbackCount:JDBC 回滚次数
并发统计:
ConcurrentMax:最大并发数RunningCount:当前运行数JdbcRunningCount:当前 JDBC 运行数
6. Prometheus 集成
6.1 安装 MySQL Exporter
MySQL Exporter 用于将 MySQL 指标导出到 Prometheus。
bash
# 拉取镜像
docker pull prom/mysqld-exporter
# 运行容器
docker run -d \
--name mysqld-exporter \
-p 9104:9104 \
-e DATA_SOURCE_NAME="root:password@(192.168.1.10:3306)/" \
--restart=always \
prom/mysqld-exporter6.2 配置 Prometheus 采集 MySQL 指标
编辑 prometheus.yml:
yaml
scrape_configs:
- job_name: 'mysql'
static_configs:
- targets: ['192.168.1.10:9104']
labels:
instance: 'mysql-1'
env: 'dev'6.3 MySQL 监控指标
连接指标:
mysql_global_status_threads_connected:当前连接数mysql_global_status_max_used_connections:最大连接数mysql_global_status_threads_running:运行中的线程数
查询指标:
mysql_global_status_questions:查询总数mysql_global_status_queries:查询速率mysql_global_status_slow_queries:慢查询数
缓冲池指标:
mysql_global_status_innodb_buffer_pool_reads:缓冲池读取次数mysql_global_status_innodb_buffer_pool_read_requests:缓冲池读取请求mysql_global_status_innodb_buffer_pool_size:缓冲池大小
复制指标:
mysql_slave_status_seconds_behind_master:从库延迟时间
7. Grafana 仪表板
7.1 导入 MySQL 仪表板
- 登录 Grafana
- 进入"Dashboards" -> "Import"
- 输入仪表板 ID:
7362(MySQL Overview) - 点击"Load"
- 选择 Prometheus 数据源
- 点击"Import"
7.2 自定义 MySQL 仪表板
创建自定义仪表板,监控以下指标:
连接监控:
- 当前连接数
- 最大连接数
- 连接使用率
查询监控:
- 查询速率
- 慢查询数
- 查询响应时间
缓冲池监控:
- 缓冲池大小
- 缓冲池命中率
- 缓冲池读取速率
复制监控:
- 从库延迟
- 复制状态
8. 告警配置
8.1 配置 MySQL 告警规则
创建 /data/prometheus/rules/mysql.yml:
yaml
groups:
- name: mysql_alerts
interval: 30s
rules:
# MySQL 宕机告警
- alert: MySQLDown
expr: mysql_up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "MySQL 实例 {{ $labels.instance }} 宕机"
description: "MySQL 实例 {{ $labels.instance }} 已经宕机超过 1 分钟"
# 高连接数告警
- 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 实例 {{ $labels.instance }} 连接数超过 80%,当前值为 {{ $value }}%"
# 慢查询告警
- alert: MySQLSlowQueries
expr: rate(mysql_global_status_slow_queries[5m]) > 10
for: 5m
labels:
severity: warning
annotations:
summary: "MySQL 实例 {{ $labels.instance }} 慢查询过多"
description: "MySQL 实例 {{ $labels.instance }} 慢查询速率超过 10 次/分钟,当前值为 {{ $value }}"
# 缓冲池命中率告警
- alert: MySQLLowBufferPoolHitRate
expr: (1 - (rate(mysql_global_status_innodb_buffer_pool_reads[5m]) / rate(mysql_global_status_innodb_buffer_pool_read_requests[5m]))) * 100 < 95
for: 10m
labels:
severity: warning
annotations:
summary: "MySQL 实例 {{ $labels.instance }} 缓冲池命中率过低"
description: "MySQL 实例 {{ $labels.instance }} 缓冲池命中率低于 95%,当前值为 {{ $value }}%"
# 从库延迟告警
- alert: MySQLReplicationLag
expr: mysql_slave_status_seconds_behind_master > 60
for: 5m
labels:
severity: warning
annotations:
summary: "MySQL 从库 {{ $labels.instance }} 延迟过高"
description: "MySQL 从库 {{ $labels.instance }} 延迟超过 60 秒,当前值为 {{ $value }} 秒"9. 慢查询分析
9.1 开启慢查询日志
编辑 MySQL 配置文件 my.cnf:
ini
[mysqld]
# 开启慢查询日志
slow_query_log = 1
# 慢查询日志文件路径
slow_query_log_file = /var/log/mysql/slow-query.log
# 慢查询阈值(秒)
long_query_time = 2
# 记录未使用索引的查询
log_queries_not_using_indexes = 1
# 记录管理语句
log_slow_admin_statements = 19.2 分析慢查询
使用 mysqldumpslow 工具分析慢查询:
bash
# 查看最慢的 10 条 SQL
mysqldumpslow -s t -t 10 /var/log/mysql/slow-query.log
# 查看访问次数最多的 10 条 SQL
mysqldumpslow -s c -t 10 /var/log/mysql/slow-query.log
# 查看返回记录数最多的 10 条 SQL
mysqldumpslow -s r -t 10 /var/log/mysql/slow-query.log9.3 优化慢查询
根据慢查询日志,分析并优化 SQL 语句:
- 添加合适的索引
- 优化 SQL 语句
- 优化表结构
- 使用缓存
10. 性能优化
10.1 连接池优化
yaml
spring:
datasource:
druid:
# 根据实际情况调整连接池大小
initial-size: 10
min-idle: 20
max-active: 50
# 调整获取连接等待时间
max-wait: 10000
# 调整连接检测间隔
time-between-eviction-runs-millis: 60000
# 调整连接最小生存时间
min-evictable-idle-time-millis: 30000010.2 SQL 优化
- 使用索引
- 避免 SELECT *
- 避免 OR 条件
- 使用 LIMIT 分页
- 使用 JOIN 替代子查询
- 使用 EXPLAIN 分析 SQL
10.3 MySQL 优化
ini
[mysqld]
# 调整缓冲池大小(建议设置为物理内存的 70-80%)
innodb_buffer_pool_size = 4G
# 调整缓冲池实例数
innodb_buffer_pool_instances = 4
# 调整日志文件大小
innodb_log_file_size = 512M
# 调整日志缓冲区大小
innodb_log_buffer_size = 16M
# 调整最大连接数
max_connections = 500
# 调整查询缓存
query_cache_size = 0
query_cache_type = 011. 常见问题
11.1 Druid 监控页面无法访问
问题:无法访问 Druid 监控页面
解决方案:
- 检查
stat-view-servlet.enabled是否为true - 检查安全配置是否允许访问
/druid/** - 检查防火墙是否开放端口
- 检查用户名密码是否正确
11.2 连接池耗尽
问题:连接池耗尽,无法获取连接
解决方案:
- 增加
max-active连接数 - 检查是否有连接泄漏
- 优化 SQL 执行时间
- 检查是否有长事务
11.3 慢查询过多
问题:慢查询数量过多
解决方案:
- 开启慢查询日志
- 分析慢查询日志
- 优化 SQL 语句
- 添加合适的索引
- 优化表结构
11.4 MySQL Exporter 无法采集指标
问题:MySQL Exporter 无法采集指标
解决方案:
- 检查 MySQL 是否运行
- 检查连接配置是否正确
- 检查用户权限是否足够
- 检查网络连接是否正常
12. 注意事项
- 连接池配置:根据实际情况调整连接池大小
- 慢查询监控:定期分析慢查询日志
- 索引优化:合理使用索引提高查询性能
- 告警配置:配置合理的告警规则
- 日志管理:定期清理日志文件
- 安全配置:限制监控页面访问
- 备份策略:定期备份数据库
- 性能监控:持续监控数据库性能
