searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

线上 MySQL 数据库连接打满排查指南

2025-04-01 09:40:05
4
0

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 连接泄漏检测

代码检查要点

  1. 确认所有JDBC操作都使用try-with-resources:

    try (Connection conn = dataSource.getConnection();
         PreparedStatement stmt = conn.prepareStatement(sql);
         ResultSet rs = stmt.executeQuery()) {
        // 业务处理
    }
    
  2. 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;

注:所有操作建议先在测试环境验证,生产环境操作需做好回滚方案,一定要保证数据完整性!

0条评论
0 / 1000
z****n
9文章数
0粉丝数
z****n
9 文章 | 0 粉丝
原创

线上 MySQL 数据库连接打满排查指南

2025-04-01 09:40:05
4
0

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 连接泄漏检测

代码检查要点

  1. 确认所有JDBC操作都使用try-with-resources:

    try (Connection conn = dataSource.getConnection();
         PreparedStatement stmt = conn.prepareStatement(sql);
         ResultSet rs = stmt.executeQuery()) {
        // 业务处理
    }
    
  2. 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;

注:所有操作建议先在测试环境验证,生产环境操作需做好回滚方案,一定要保证数据完整性!

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
1
1