文章目录
一、HikariCP YAML 配置详解
HikariCP 是 Spring Boot 2.x 及更高版本的默认数据库连接池,以下是完整的 YAML 配置说明和优化建议。
基础配置
spring:
datasource:
hikari:
# 连接池名称 (用于监控和日志)
pool-name: MyHikariPool
# 连接池中允许的最大连接数 (默认: 10)
maximum-pool-size: 20
# 连接池中保持的最小空闲连接数 (建议与maximum-pool-size相同)
minimum-idle: 20
# 连接超时时间 (毫秒) (默认: 30000)
connection-timeout: 30000
# 连接最大存活时间 (毫秒) (建议比数据库wait_timeout小2-3分钟)
max-lifetime: 1800000 # 30分钟
# 连接空闲超时时间 (毫秒) (默认: 600000)
idle-timeout: 600000 # 10分钟
# 连接测试查询 (部分数据库需要)
connection-test-query: SELECT 1
# 自动提交 (默认: true)
auto-commit: true
高级配置
spring:
datasource:
hikari:
# 数据源类名 (通常不需要指定)
data-source-class-name: com.zaxxer.hikari.HikariDataSource
# 连接初始化SQL (每次新建连接后执行)
connection-init-sql: SET NAMES utf8mb4
# 是否隔离自动提交事务 (默认: false)
isolate-internal-queries: false
# 是否注册JMX (默认: false)
register-mbeans: false
# 连接泄漏检测阈值 (毫秒) (0表示禁用)
leak-detection-threshold: 0
# 验证连接是否可用的超时时间 (毫秒)
validation-timeout: 5000
# 连接池准备就绪前是否阻塞应用启动 (默认: true)
initialization-fail-timeout: 1
数据库特定配置
MySQL 优化配置
spring:
datasource:
hikari:
# MySQL 推荐配置
connection-timeout: 30000
max-lifetime: 1800000 # 30分钟 (小于MySQL的wait_timeout)
idle-timeout: 600000 # 10分钟
maximum-pool-size: 20
minimum-idle: 20
connection-test-query: SELECT 1
# MySQL 连接属性
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
useServerPrepStmts: true
useLocalSessionState: true
rewriteBatchedStatements: true
cacheResultSetMetadata: true
cacheServerConfiguration: true
elideSetAutoCommits: true
maintainTimeStats: false
PostgreSQL 优化配置
spring:
datasource:
hikari:
# PostgreSQL 推荐配置
maximum-pool-size: 15
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
# PostgreSQL 连接属性
data-source-properties:
prepareThreshold: 3
preferQueryMode: extended
reWriteBatchedInserts: true
生产环境推荐配置
spring:
datasource:
hikari:
pool-name: ${spring.application.name}-HikariCP
maximum-pool-size: ${DB_POOL_SIZE:20}
minimum-idle: ${DB_POOL_MIN_IDLE:20}
max-lifetime: ${DB_MAX_LIFETIME:1800000}
connection-timeout: ${DB_CONN_TIMEOUT:30000}
idle-timeout: ${DB_IDLE_TIMEOUT:600000}
leak-detection-threshold: ${DB_LEAK_DETECTION:0}
connection-test-query: SELECT 1
# MySQL 性能优化参数
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
useServerPrepStmts: true
useLocalSessionState: true
rewriteBatchedStatements: true
配置说明与优化建议
连接池大小计算:
- 推荐公式:
connections = ((core_count * 2) + effective_spindle_count)
- 4核SSD系统:
(4*2)+1 = 9 → 设置为10-20
- 推荐公式:
max-lifetime 设置:
- 应比数据库的
wait_timeout
小2-3分钟 - MySQL默认
wait_timeout
是8小时(28800秒)
- 应比数据库的
leak-detection-threshold:
- 开发环境可设置为
60000
(1分钟)检测连接泄漏 - 生产环境建议设为
0
(禁用)以避免性能影响
- 开发环境可设置为
监控集成:
management: endpoints: web: exposure: include: health,metrics,info endpoint: health: show-details: always db: enabled: true
常见问题解决
连接泄漏错误:
hikari: leak-detection-threshold: 60000 # 1分钟检测
连接超时问题:
hikari: connection-timeout: 60000 # 增加到60秒 initialization-fail-timeout: -1 # 永不超时
MySQL 8小时问题:
hikari: max-lifetime: 28000000 # 比8小时(28800000)少80秒 connection-test-query: SELECT 1
HikariCP 的这些配置参数可以帮助您根据应用需求优化数据库连接池性能,建议根据实际监控数据不断调整优化。
二、拓展
1、什么是MySQL 8小时问题
MySQL 8小时问题是指当数据库连接空闲时间超过8小时后,MySQL服务器会自动断开连接,而连接池并不知道这个连接已经失效,导致应用尝试使用这些被断开的连接时出现错误的问题。
问题本质
MySQL默认配置:
wait_timeout
参数默认为28800秒(8小时)- 表示如果一个连接空闲超过8小时,MySQL服务器会自动关闭它
连接池行为:
- 连接池中的连接被应用使用后返回到池中
- 如果连接长时间未被使用(超过8小时),MySQL会关闭它
- 但连接池仍然认为这些连接是有效的
问题表现:
- 应用尝试使用这些"僵尸连接"时会报错:
Communications link failure The last packet successfully received from the server was X milliseconds ago
- 通常发生在应用长时间低负载运行后(如夜间)
- 应用尝试使用这些"僵尸连接"时会报错:
解决方案
1. 调整MySQL配置(不推荐)
-- 增加wait_timeout(不推荐,只是延迟问题出现时间)
SET GLOBAL wait_timeout=86400; -- 24小时
缺点:只是推迟问题发生时间,没有根本解决
2. 优化连接池配置(推荐)
HikariCP配置方案:
spring:
datasource:
hikari:
# 设置max-lifetime略小于wait_timeout(7小时50分钟)
max-lifetime: 28200000 # 7小时50分钟(单位毫秒)
# 连接测试查询
connection-test-query: SELECT 1
# 空闲连接检查
idle-timeout: 600000 # 10分钟空闲后检查
Druid配置方案:
spring:
datasource:
druid:
# 定期检查空闲连接
time-between-eviction-runs-millis: 60000 # 60秒检查一次
min-evictable-idle-time-millis: 1800000 # 30分钟空闲就回收
test-while-idle: true # 检查空闲连接有效性
validation-query: SELECT 1
3. 最佳实践组合
设置合理的max-lifetime:
- 比MySQL的wait_timeout少2-3分钟
- 例如:
max-lifetime: 28000000
(7小时46分40秒)
启用连接测试:
hikari: connection-test-query: SELECT 1 # 或者使用更好的validation-timeout validation-timeout: 5000
定期心跳(适合生产环境):
-- 在MySQL中设置 SET GLOBAL interactive_timeout = 3600; SET GLOBAL wait_timeout = 3600;
问题验证方法
查看当前MySQL超时设置:
SHOW VARIABLES LIKE 'wait_timeout'; SHOW VARIABLES LIKE 'interactive_timeout';
模拟测试:
- 将wait_timeout设为很短时间(如60秒)
- 观察连接池行为
监控连接状态:
SHOW PROCESSLIST;
其他注意事项
不同驱动的影响:
- MySQL Connector/J 8.0+有更好的连接失效检测机制
- 建议使用最新驱动
云数据库差异:
- AWS RDS/Aurora等可能有不同的默认超时设置
- 需要检查云服务商的具体配置
连接泄漏的混淆:
- 真正的连接泄漏也会导致类似错误
- 需要区分是8小时问题还是应用代码泄漏连接
通过合理配置连接池参数和MySQL参数,可以完全避免8小时问题,确保应用稳定运行。