数据库连接池优化:HikariCP与Druid实战

数据库连接池,说白了就是MES系统的命脉。我见过太多系统,业务逻辑写得再漂亮,最后都死在连接池上。今天咱们就聊聊HikariCP和Druid这两个主流连接池,我会把配置参数、踩坑经验都抖出来。

核心观点:连接池不是越大越好,也不是越快越好。关键是要找到那个「刚刚好」的点。

2.1 连接池的核心参数

先说说最关键的几个参数。我个人习惯,不管用哪个连接池,都会先盯住这三个:最大连接数、超时时间、连接泄漏检测。

参数名 HikariCP Druid 我的建议值
最大连接数 maximumPoolSize maxActive CPU核心数×2 + 1
最小空闲连接 minimumIdle minIdle 最大连接数的1/4
连接超时 connectionTimeout maxWait 30000ms(30秒)
空闲超时 idleTimeout minEvictableIdleTimeMillis 600000ms(10分钟)
最大存活时间 maxLifetime maxEvictableIdleTimeMillis 1800000ms(30分钟)

你可能会问,为什么最大连接数要按CPU核心数来算?嗯,这里有个误区。很多人觉得连接数越多越好,其实不然。连接数太多,数据库CPU上下文切换反而更频繁,性能会下降。我在项目中遇到过,把最大连接数从200调到50,吞吐量反而提升了30%。

2.2 HikariCP配置实战

HikariCP现在几乎是Spring Boot的默认连接池了。它轻量、快,但参数调不好照样翻车。

# application.yml 配置示例
spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      connection-test-query: SELECT 1
      validation-timeout: 5000
      leak-detection-threshold: 60000

我的小技巧:leak-detection-threshold 这个参数一定要设。设成60秒,如果某个连接被占用超过60秒,HikariCP就会打印警告日志。我曾经靠这个参数抓到一个慢SQL,那个SQL跑了45秒,把整个连接池都堵死了。

2.3 Druid配置实战

Druid在监控方面比HikariCP强很多。如果你需要详细的SQL执行统计,Druid是不二之选。

# Druid配置示例
spring:
  datasource:
    druid:
      initial-size: 5
      max-active: 20
      min-idle: 5
      max-wait: 30000
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      filters: stat,wall,log4j2
      connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

注意:test-on-borrow 和 test-on-return 这两个参数,我建议都设成false。为什么?因为每次借出和归还连接都做校验,性能损耗太大。用 test-while-idle 就够了,它会在空闲时异步检测连接有效性。

2.4 连接泄漏检测

连接泄漏是MES系统最常见的坑之一。说白了就是代码里拿了连接没归还,时间长了连接池就枯竭了。

我曾经在一个MES项目里,生产环境每隔3小时就报「无法获取连接」的错误。查了两天才发现,是某个业务逻辑里try-catch之后,finally块忘了关闭PreparedStatement。嗯,就这一行代码,坑了全组人。

怎么检测?两个办法:

  • 日志分析:开启连接池的泄漏检测日志,看哪个连接长时间没归还
  • 监控工具:Druid自带监控页面,能看到活跃连接数和等待队列长度

避坑指南:我曾经在代码里用ThreadLocal缓存了数据库连接,想着能复用。结果线程池里的线程被回收时,连接没归还。这个坑我踩了整整一周。记住:永远不要在ThreadLocal里存数据库连接!

2.5 我踩过的三个大坑

做MES系统这么多年,连接池上栽的跟头不少。挑三个最典型的说说:

  1. 最大连接数设太大:一个MES产线有200台设备,我一开始把最大连接数设成了200。结果数据库CPU直接飙到100%,连接池里全是TIME_WAIT。后来压到30,反而稳了。
  2. 超时时间设太短:有次把connectionTimeout设成了5秒,结果MES系统里有个报表查询要跑8秒,频繁报超时。后来改成30秒,问题解决。但治标不治本,最后还是优化了那个SQL。
  3. 没开连接泄漏检测:这个最要命。系统运行了两个月,突然有一天所有接口都返回500。查了半天,是某个定时任务里连接没释放。从那以后,我每个项目都会强制开启泄漏检测。

2.6 性能对比与选型建议

直接说结论:

场景 推荐连接池 理由
高并发、低延迟 HikariCP 性能极致,启动快
需要SQL监控 Druid 监控功能强大,有防火墙
中小型MES系统 HikariCP 配置简单,够用
大型MES系统 Druid 需要慢SQL分析和告警

我个人习惯,新项目默认用HikariCP。如果客户要求有SQL审计功能,再切到Druid。你想想看,HikariCP的代码量只有Druid的十分之一,出问题的概率自然小很多。

2.7 知识体系图

下面这张图,把连接池优化的核心逻辑串起来了:

数据库连接池优化知识体系 连接池优化 配置参数调优 连接泄漏检测 连接池选型 最大连接数 超时时间 空闲超时 最大存活时间 日志检测 监控工具 泄漏阈值设置 代码审查 HikariCP Druid 性能优先 监控优先 核心原则 连接数不是越多越好,超时不是越短越好 泄漏检测必须开,监控工具必须配

2.8 总结

连接池优化,说白了就是三个字:刚刚好。连接数刚刚好,超时刚刚好,检测刚刚好。别贪多,别图快,稳才是MES系统的第一要务。

最后送大家一句话:连接池的问题,90%都是代码没写好,10%才是配置没调对。先把代码写干净,再来调参数,顺序别搞反了。