楼层: 首页/ 软件技术/ JavaEE / Jakarta EE/ 数据库连接池:别每次都重新握手
05

数据库连接池:别每次都重新握手

Connection Pool · HikariCP · Druid

上面的 JDBC 代码每查一次就 getConnection 开一次连接、用完关掉。但建立数据库连接是很贵的操作(要 TCP 握手、认证、分配内存)——一秒钟来 1000 个请求,就开 1000 次连接,数据库直接被你累死。连接池(Connection Pool)就是预先养一批连接放在池子里,用了还回来,复用。

为什么不能自己 new 一个 ArrayList<Connection> 凑合?连接的"借"和"还"要防并发:两个人同时借走同一个连接怎么办?连接死了怎么踢出去?空闲连接怎么保活?这些边界条件连接池全替你处理好了,自己写一个 bug 一堆。用成熟的轮子。

HikariCP → Spring Boot 默认,性能最快
字节码级优化,业界最快的连接池,轻量。
人话:没什么花架子,就是快。Spring Boot 默认自带,零配置就能用。
Druid → 阿里开源,带监控面板
能看 SQL 执行统计、慢查询、连接数,国内项目用得多。
人话:比 HikariCP 多个"监控后台",想知道哪条 SQL 拖慢网站时用它。配好后访问 /druid/index.html,就能看到每条 SQL 跑了多少次、最慢是哪条。

初学不纠结选哪个:HikariCP 跟 Spring Boot 默认走,出问题再换 Druid 看监控。两者都实现 javax.sql.DataSource 接口,换实现只是换个配置,业务代码一行不改。

HikariCP 最小配置(Java 代码方式)

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/testdb?characterEncoding=utf8");
config.setUsername("root");
config.setPassword("你的密码");
config.setMaximumPoolSize(10);      // 池子最多养 10 个连接
config.setMinimumIdle(5);         // 闲时保底留 5 个

HikariDataSource ds = new HikariDataSource(config);

// 以后用连接,从池子借:用完 close() 不是真关,是还回池子
try (Connection conn = ds.getConnection()) {
    // ... 正常 JDBC 操作 ...
}

连接池关键参数:知道每个旋钮管什么

参数管什么
maximumPoolSize池子最多几个连接。不是越大越好,见下方警告。
minimumIdle闲时保底保持几个连接,避免冷启动。
connectionTimeout拿不到连接最多等多久(毫秒),超时直接抛异常,别无限等。
idleTimeout空闲多久后回收多余连接。
maxLifetime一个连接最长活多久,定期换新鲜连接(数据库那边也会主动踢久连接)。
池大小不是越大越好

连接池开 500 个连接?错。数据库 CPU 就那么几个核,连接多了反而在抢 CPU、上下文切换,吞吐下降。经验值:池大小 ≈ CPU 核数 * 2 左右起步,再压测调。另外 getConnection() 记得设超时,池子满了拿不到连接时别无限等。

章末面试 · 连接池(3 题)

1.(概念题)为什么不能每次请求都 DriverManager.getConnection()?

查看答案

答案:建连接很贵(TCP 握手+认证+内存分配),一秒 1000 请求就建 1000 次连接,数据库直接累死。连接池预养一批连接复用。

2.(概念题)连接池 close() 是真关连接吗?

查看答案

答案:不是。从池子借的 Connection,close() 是把连接还回池子,不是真的 TCP 关闭。这也是为什么用完必须 close——不还就泄漏。

3.(思考题)池大小设多大合适?越大越好吗?

查看答案

答案:不是。经验值 CPU 核数 * 2 起步。连接多了反而抢 CPU、上下文切换,吞吐下降。先小再压测调。