先上报错截图

1.梳理mysql,druid,jdbc在调用整个sql的调用链路
Java 程序执行一个 SQL 时,真正发生的过程:
-
应用层:业务代码(如
mapper.update())调用数据库。 -
JDBC 层:JDBC 是 Java 官方定义的一套数据库访问标准 API,它不关心你用哪个数据库(MySQL、PostgreSQL...),只定义标准接口。
-
Druid 层:Druid 是阿里巴巴开发的 JDBC 实现 + 连接池中间层。
-
它负责:
-
管理连接池(复用连接,减少频繁创建)
-
检查连接是否可用
-
控制超时与最大等待时间
-
执行 SQL 监控、慢 SQL 日志、防火墙(wall)
-
-
它内部依然使用 JDBC 接口和 MySQL 驱动进行通信。
-
-
MySQL 层:最终 Druid 通过 JDBC 驱动连接 MySQL 服务端并发送 SQL。
2.druid连接池,池化管理jdbc连接的好处
jdbc操作数据库本质上还是建立TCP连接
-
建立物理连接:应用程序向MySQL发起连接请求。
-
TCP三次握手:首先在网络层建立TCP连接。
-
MySQL认证握手:MySQL服务器对用户名、密码等进行验证。
-
执行SQL:认证成功后,执行具体的SQL查询或操作。
-
关闭连接:操作完成后,关闭连接。
-
TCP四次挥手:断开TCP连接。
这个过程的瓶颈在于第1-3步和第5-6步。 建立和断开物理连接是一个重量级的操作,非常消耗资源,所以得使用用连接池进行管理
3.druid配置对整个数据库调用过程的影响

这六个参数中,
-
maxActive和maxWait控制“并发上限”; -
initial-size、min-idle控制“启动速度与预热”; -
timeBetweenEvictionRunsMillis、minEvictableIdleTimeMillis控制“稳定性与资源回收”。
个人理解,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 前缀模糊查询 %xxx | WHERE 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...



2637

被折叠的 条评论
为什么被折叠?



