数据库连接池配置

面试官问:"数据库连接池怎么配置?"

小张说:"设置最大连接数大一点就行了。"

面试官追问:"连接数太大或太小有什么问题?"

小张说:"太小会排队等待,太大...资源不够?"

面试官继续追问:"那 MySQL 的 max_connections 是多少?连接数和 QPS 是什么关系?"

小张开始答不上来。

连接池是 MySQL 应用架构中最容易被忽视的组件。配置不合理会导致连接耗尽、线程数过多、或者资源浪费。这道题考的是候选人对数据库连接资源管理的理解深度。

一、连接池的核心概念 🔴

1.1 连接池的作用

应用服务器                          MySQL 服务器
┌────────────────┐                  ┌────────────────┐
│  连接池        │                  │                │
│  ┌──────────┐  │                  │  max_connections│
│  │连接1     │◄┼──────────────────┼─►│              │
│  │连接2     │◄┼──────────────────┼─►│              │
│  │连接3     │◄┼──────────────────┼─►│              │
│  │...       │  │                  │  │              │
│  │连接50    │◄┼──────────────────┼─►│              │
│  └──────────┘  │                  │                │
└────────────────┘                  └────────────────┘

连接池:复用连接,避免频繁建立/断开连接的开销

1.2 连接池 vs 裸连接

-- ❌ 裸连接:每次请求都建立新连接
Connection conn = DriverManager.getConnection(url, user, pwd);
-- TCP 三次握手 + MySQL 认证 = 50~500ms 开销

-- ✅ 连接池:复用已有连接
Connection conn = connectionPool.getConnection();
-- 从池中获取 = 1~5ms

1.3 MySQL 连接的限制

-- 查看 MySQL 最大连接数
SHOW VARIABLES LIKE 'max_connections';
-- 默认 151(历史遗留值)

-- 查看当前连接数
SHOW STATUS LIKE 'Threads_connected';
-- 查看最大连接数峰值
SHOW STATUS LIKE 'Max_used_connections';

二、核心配置参数 🔴

2.1 连接池核心参数

参数说明推荐值
maximumPoolSize最大连接数CPU 核心数 × 2 + 磁盘数
minimumIdle最小空闲连接5~10
connectionTimeout获取连接超时30 秒
idleTimeout空闲连接回收时间10 分钟
maxLifetime连接最大生命周期30 分钟

2.2 连接数配置计算

-- 假设:
-- 应用服务器:4 台
-- 每台最大连接数:50
-- MySQL max_connections = 4 × 50 = 200

-- 推荐保留一些余量
-- MySQL max_connections = 200 + 20 = 220

2.3 连接数过大的问题

-- 症状:
-- 1. MySQL CPU 使用率不高,但响应慢
-- 2. SHOW PROCESSLIST 显示大量连接
-- 3. "Too many connections" 错误

-- 原因:
-- 1. 应用连接池 maximumPoolSize 设置过大
-- 2. 慢查询导致连接长时间占用
-- 3. 连接泄漏(未正确关闭连接)

2.4 ❌ 错误示范

候选人原话:"max_connections 设成 10000,够用。"

问题诊断:MySQL 单线程处理连接,连接数过多会导致:

  • 上下文切换开销大
  • 每个连接占用内存(默认 256KB/连接)
  • 10000 连接 = 2.5GB 内存开销

候选人原话 2:"连接池越大越好。"

问题诊断:连接数过大会导致资源争用。每个连接都要占用 CPU 和内存,连接太多反而降低吞吐量。

【面试官心理】 这道题我会从实际配置问题切入。如果候选人能说清楚连接数和 QPS 的关系、连接超时设置、以及连接泄漏的排查方法,说明他有生产经验。

三、连接池调优 🟡

3.1 HikariCP 推荐配置

// HikariCP 推荐配置示例
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20);      // 核心数 × 2
config.setMinimumIdle(5);           // 保持最小空闲
config.setConnectionTimeout(30000); // 30 秒获取超时
config.setIdleTimeout(600000);      // 10 分钟空闲回收
config.setMaxLifetime(1800000);     // 30 分钟最大生命周期
config.setConnectionTestQuery("SELECT 1");  // 连接检测

3.2 Druid 连接池配置

// Druid 配置
DruidDataSource dataSource = new DruidDataSource();
dataSource.setInitialSize(10);           // 初始连接数
dataSource.setMaxActive(50);              // 最大活跃连接
dataSource.setMinIdle(5);                 // 最小空闲
dataSource.setMaxWait(60000);             // 最大等待时间
dataSource.setTimeBetweenEvictionRunsMillis(60000); // 检测间隔
dataSource.setValidationQuery("SELECT 1"); // 连接检测 SQL
dataSource.setTestWhileIdle(true);        // 空闲时检测

3.3 连接超时设置

-- MySQL 端:连接超时
SHOW VARIABLES LIKE 'wait_timeout';
-- 默认 8 小时(28800 秒)
-- 空闲连接 8 小时无活动,MySQL 自动断开

-- 应用端:连接超时
-- connectionTimeout 设置要小于 MySQL 的 wait_timeout
-- 否则:应用以为连接有效,MySQL 已断开

四、生产避坑 🟡

4.1 连接泄漏

-- 症状:
-- 应用连接数持续增长,最终耗尽 max_connections
SHOW STATUS LIKE 'Threads_connected';  -- 持续增长

-- 原因:连接未正确关闭
-- try {
--     conn = pool.getConnection();
--     // 业务逻辑
--     return result;  // 连接未关闭!
-- } finally {
--     conn.close();   // 应该在这里关闭
-- }

4.2 慢查询占用连接

-- 慢查询占用连接时间过长
-- 一个查询 30 秒,占用一个连接 30 秒
-- 连接池 20 个,QPS 只能到 20/30 = 0.67 QPS

-- 解决:
-- 1. 优化慢查询
-- 2. 设置查询超时:SET SESSION MAX_EXECUTION_TIME = 5000;  -- 5 秒

4.3 监控告警

-- 监控连接数使用率
SELECT
    VARIABLE_VALUE as current_connections
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME = 'THREADS_CONNECTED';

-- 监控可用连接
SELECT
    VARIABLE_VALUE as max_connections
FROM information_schema.GLOBAL_VARIABLES
WHERE VARIABLE_NAME = 'MAX_CONNECTIONS';

-- 告警条件:
-- 当前连接数 > max_connections × 80%

【面试官心理】 连接池配置的候选人里,能说出连接泄漏问题和慢查询占用连接的是少数。真正有生产经验的候选人,应该能说出"为什么要设置 maxLifetime"、"连接超时怎么设置"的实际原因。


级别考察重点期望回答
P5基础概念连接池作用、核心参数
P6配置调优连接数计算、超时设置
P7生产经验连接泄漏、慢查询占用连接、监控告警