1. 确认问题现象
典型表现
- 应用日志出现
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Too many connections
- 监控平台显示数据库连接数达到
max_connections
阈值 - 应用出现大量数据库操作超时
紧急处理方案
-- 临时增加最大连接数(需super权限)
SET GLOBAL max_connections = 500; -- 根据服务器配置调整
-- 安全清理空闲连接(示例清理超过10分钟的空闲连接)
SELECT CONCAT('KILL ', id, ';')
FROM information_schema.processlist
WHERE COMMAND = 'Sleep' AND TIME > 600
INTO OUTFILE '/tmp/kill_idle.sql';
SOURCE /tmp/kill_idle.sql;
2. 深度排查步骤
2.1 连接来源分析
-- 查看完整连接信息
SELECT
id,
USER,
HOST,
DB,
COMMAND,
TIME,
STATE,
LEFT(INFO, 100) AS query_snippet
FROM information_schema.processlist
ORDER BY TIME DESC;
-- 按用户/IP统计连接数
SELECT
USER,
SUBSTRING_INDEX(HOST, ':', 1) AS client_ip,
COUNT(*) AS connection_count,
GROUP_CONCAT(DISTINCT DB) AS databases
FROM information_schema.processlist
GROUP BY USER, SUBSTRING_INDEX(HOST, ':', 1)
ORDER BY connection_count DESC;
2.2 连接泄漏检测
代码检查要点
-
确认所有JDBC操作都使用try-with-resources:
try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery()) { // 业务处理 }
-
Spring事务边界检查:
@Transactional // 确保不会在事务内进行长时间操作,如有必要,添加异常回滚机制 public void process() { // 业务逻辑 }
连接池监控配置(HikariCP示例)
注意:根据生产环境数据库实际性能配置
spring:
datasource:
hikari:
leak-detection-threshold: 10000 # 10秒泄漏检测
maximum-pool-size: 50 # 根据DB配置调整
idle-timeout: 60000 # 1分钟空闲超时
max-lifetime: 1800000 # 30分钟最大生命周期
2.3 慢查询分析
-- 启用慢查询日志(需在my.cnf永久配置)
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1; # 1秒阈值
SET GLOBAL log_queries_not_using_indexes = 1;
-- 实时查看运行中的慢查询
SELECT * FROM information_schema.processlist
WHERE TIME > 5 AND INFO IS NOT NULL
ORDER BY TIME DESC;
3. 根本原因分析
常见原因
原因类型 | 特征表现 | 验证方法 |
---|---|---|
连接泄漏 | 连接数随时间持续增长不释放 | 检查连接池active计数 |
慢查询阻塞 | 大量连接处于"Sending data"状态 | 分析processlist和慢日志 |
事务未提交 | 连接处于"sleep"但TIME值极大 | 查询INNODB_TRX表 |
连接池配置不当 | 连接池maxSize接近DB max_connections | 对比应用和DB配置 |
突发流量 | 监控显示QPS陡增 | 分析流量监控图表 |
4. 解决方案
4.1 连接泄漏修复
// 正确关闭连接示例
public List<User> getUsers() {
String sql = "SELECT * FROM users";
try (Connection conn = dataSource.getConnection(); // 自动关闭
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
return mapUsers(rs);
} catch (SQLException e) {
throw new DataAccessException(e);
}
}
4.2 慢查询优化
-- 添加适当索引
ALTER TABLE orders ADD INDEX idx_status_created (status, created_at);
-- 优化查询语句
EXPLAIN SELECT * FROM orders WHERE status = 'PENDING' ORDER BY created_at DESC;
4.3 配置调优
ini
# my.cnf 关键配置
[mysqld]
max_connections = 1000
wait_timeout = 300
interactive_timeout = 300
table_open_cache = 4000
5. 预防措施
监控体系搭建
# Prometheus监控配置示例
- job_name: 'mysql'
metrics_path: '/metrics'
static_configs:
- targets: ['mysql-host:9104'] # 使用mysqld_exporter
告警规则
# Alertmanager规则示例
groups:
- name: mysql-alerts
rules:
- alert: HighConnections
expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "MySQL连接数过高 ({{ $value }}%)"
6. 高级工具
工具名称 | 用途 | 使用示例 |
---|---|---|
pt-kill | 智能终止问题查询 | pt-kill --busy-time 60 --kill |
MySQLTuner | 配置优化建议 | perl mysqltuner.pl |
VividCortex | 实时查询分析 | SaaS监控平台 |
Orchestrator | 高可用管理 | 自动故障转移 |
附录:关键SQL命令速查
-- 查看所有变量
SHOW GLOBAL VARIABLES LIKE '%connect%';
-- 查看运行状态
SHOW GLOBAL STATUS LIKE 'Thread%';
-- 查看锁等待
SELECT * FROM performance_schema.events_waits_current;
注:所有操作建议先在测试环境验证,生产环境操作需做好回滚方案,一定要保证数据完整性!