MYSQL超时连接问题排查

先上报错截图

1.梳理mysql,druid,jdbc在调用整个sql的调用链路

Java 程序执行一个 SQL 时,真正发生的过程:

  1. 应用层:业务代码(如 mapper.update())调用数据库。

  2. JDBC 层:JDBC 是 Java 官方定义的一套数据库访问标准 API,它不关心你用哪个数据库(MySQL、PostgreSQL...),只定义标准接口。

  3. Druid 层:Druid 是阿里巴巴开发的 JDBC 实现 + 连接池中间层

    • 它负责:

      • 管理连接池(复用连接,减少频繁创建)

      • 检查连接是否可用

      • 控制超时与最大等待时间

      • 执行 SQL 监控、慢 SQL 日志、防火墙(wall)

    • 它内部依然使用 JDBC 接口和 MySQL 驱动进行通信。

  4. MySQL 层:最终 Druid 通过 JDBC 驱动连接 MySQL 服务端并发送 SQL。

2.druid连接池,池化管理jdbc连接的好处

jdbc操作数据库本质上还是建立TCP连接

  1. 建立物理连接:应用程序向MySQL发起连接请求。

  2. TCP三次握手:首先在网络层建立TCP连接。

  3. MySQL认证握手:MySQL服务器对用户名、密码等进行验证。

  4. 执行SQL:认证成功后,执行具体的SQL查询或操作。

  5. 关闭连接:操作完成后,关闭连接。

  6. TCP四次挥手:断开TCP连接。

这个过程的瓶颈在于第1-3步和第5-6步。 建立和断开物理连接是一个重量级的操作,非常消耗资源,所以得使用用连接池进行管理

3.druid配置对整个数据库调用过程的影响

这六个参数中,

  • maxActivemaxWait 控制“并发上限”;

  • initial-sizemin-idle 控制“启动速度与预热”;

  • timeBetweenEvictionRunsMillisminEvictableIdleTimeMillis 控制“稳定性与资源回收”。

个人理解,druid配置只是负责控制系统对数据库操作的并发能力,动态调整连接池的连接,控制连接资源。

4.jdbc连接参数socketTimeOut的影响

 url: jdbc:mysql://127.0.0.1:13306/XXX?characterEncoding=UTF-8&socketTimeout=30000&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai

socketTimeOut如果没有配置,默认值为0,无限等待;

配置30000毫秒,如果30S内mysql没有返回结果,客户端主动断开,报连接超时

5.mysql超时连接参数connect_timeout

这个参数只在连接时生效,也就是说等待客户端连接响应时间,如果超过指定参数,客户端主动断开连接

6.排查是否mysql事务卡住,mysql执行SHOW PROCESSLIST;

出现状态为Waiting for table metadata lock,表示事务锁卡住了

7.查看mysql的并发情况

查看结果如下,绰绰有余,说明并不是客户端大量并发导致的

SHOW STATUS LIKE 'Threads_connected';   当前线程连接数   26
SHOW STATUS LIKE 'Threads_running';        当前活跃的连接数 2
SHOW VARIABLES LIKE 'max_connections'; 可以保持的最大连接数 200

8.进入druid监控页面,排查慢sql,优化系统

登录地址:系统路径+/druid/sql.html

1.点击最慢,排查时间分布,查看是否存在慢sql

SQL执行时间分布(毫秒):
0-1ms | 1-10ms | 10-100ms | 100-1000ms | 1-10s | 10-100s | >100s

2.是否存在频繁操作数据库代码

查看sql执行时间分布在秒级的情况,如果存在大量的秒级,需要排查系统逻辑,优化sql对应系统代码,是否存在频繁查库/更新库的代码

3.如果没有频繁操作数据库的代码,查看对应表的数据量,是否有无索引

9.执行explain分析sql索引情况(explain + sql)

explain SELECT COUNT(*) AS total FROM ircm_task_detail WHERE status = 1 AND robot_code = '1'

执行后会输出一张表,常见字段如下 ,排查索引的使用情况

列名说明
id查询中每个 SELECT 的编号(越大越先执行)
select_type查询类型(如 SIMPLE、PRIMARY、SUBQUERY)
table当前访问的表
partitions分区信息(若用到分区表)
type访问类型(最重要)
possible_keys可能用到的索引
key实际使用的索引
key_len索引长度(用于判断联合索引的使用程度)
ref哪个列或常量与索引做比较
rows预估扫描行数(越小越好)
filtered预估过滤比例(%)
Extra额外信息(是否排序、临时表等)

10.排查索引失效情况

编号失效原因举例解决方式
使用函数或表达式WHERE YEAR(create_time)=2025改写为区间查询
LIKE 前缀模糊查询 %xxxWHERE name LIKE '%abc'改写为右匹配 or 全文索引
OR 条件中某列没索引WHERE id=1 OR age=20拆分或用 UNION
类型不匹配(隐式转换)WHERE id='123'(id为INT)参数类型保持一致
在索引列上进行运算WHERE age+1=30改成 WHERE age=29
联合索引未遵守“最左前缀原则”索引 (a,b,c) 但只查 b按索引顺序写条件
范围查询导致右侧字段失效WHERE a>10 AND b=20(索引a,b)拆分索引或优化顺序
IS NULL / IS NOT NULL 使用不当WHERE col IS NOT NULL适当使用默认值或函数索引
数据分布极度不均(低选择性)WHERE gender='M'无法优化,全表扫描更快
ORDER BY / GROUP BY 未使用索引顺序ORDER BY other_col保持索引字段顺序一致

11.mysql waitTimeOut超时参数,默认8小时

SHOW VARIABLES LIKE 'wait_timeout';
  • 如果你用 连接池(如 Druid、HikariCP),应用连接 MySQL 后长时间无操作,超过 8 小时就会被 MySQL 服务端主动断开。

  • 应用端如果没有正确处理断开的连接,下一次查询会报错:

    Communications link failure The last packet successfully received from the server was 28800 milliseconds ago...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值