【java】Druid数据库连接池完整配置指南:从入门到生产环境优化

文章目录

  • [1. 引言:为什么选择 Druid 作为数据库连接池?](#1. 引言:为什么选择 Druid 作为数据库连接池?)
  • [2. Spring Boot 中集成 Druid 的基本步骤](#2. Spring Boot 中集成 Druid 的基本步骤)
      • [2.1 方式一:使用官方 Starter(推荐)](#2.1 方式一:使用官方 Starter(推荐))
      • [2.2 方式二:自定义配置类(传统方式)](#2.2 方式二:自定义配置类(传统方式))
  • [3. 连接池核心参数解析:从初始化到销毁](#3. 连接池核心参数解析:从初始化到销毁)
    • [3.1 连接池大小配置](#3.1 连接池大小配置)
      • [initial-size: 5](#initial-size: 5)
      • [min-idle: 5](#min-idle: 5)
      • [maxActive: 50](#maxActive: 50)
      • [maxWait: 60000](#maxWait: 60000)
    • [3.2 连接有效性检测](#3.2 连接有效性检测)
      • [timeBetweenEvictionRunsMillis: 60000](#timeBetweenEvictionRunsMillis: 60000)
      • [minEvictableIdleTimeMillis: 300000](#minEvictableIdleTimeMillis: 300000)
      • [validationQuery: SELECT 1](#validationQuery: SELECT 1)
      • [validationQueryTimeout: 5](#validationQueryTimeout: 5)
    • [3.3 检测策略配置](#3.3 检测策略配置)
      • [testWhileIdle: true](#testWhileIdle: true)
      • [testOnBorrow: false](#testOnBorrow: false)
      • [testOnReturn: false](#testOnReturn: false)
    • [3.4 连接池参数配置建议](#3.4 连接池参数配置建议)
  • [4. 监控配置揭秘:StatViewServlet 与 WebStatFilter](#4. 监控配置揭秘:StatViewServlet 与 WebStatFilter)
  • [5. 过滤器链:stat、wall、slf4j 的作用与原理](#5. 过滤器链:stat、wall、slf4j 的作用与原理)
    • [5.1 StatFilter:性能监控的基石](#5.1 StatFilter:性能监控的基石)
    • [5.2 WallFilter:SQL 防火墙](#5.2 WallFilter:SQL 防火墙)
    • [5.3 Slf4jLogFilter:可定制的日志输出](#5.3 Slf4jLogFilter:可定制的日志输出)
    • [5.4 过滤器链的工作流程与扩展](#5.4 过滤器链的工作流程与扩展)
  • [6. 高级特性:PSCache 与连接属性配置](#6. 高级特性:PSCache 与连接属性配置)
    • [6.1 PSCache:预编译语句缓存](#6.1 PSCache:预编译语句缓存)
      • [什么是 PreparedStatement?](#什么是 PreparedStatement?)
      • [PSCache 的工作原理](#PSCache 的工作原理)
      • 核心配置参数
      • 参数详解
        • [poolPreparedStatements: true](#poolPreparedStatements: true)
        • [maxPoolPreparedStatementPerConnectionSize: 100](#maxPoolPreparedStatementPerConnectionSize: 100)
      • [PSCache 的优缺点](#PSCache 的优缺点)
  • [7. 实战中的性能调优与常见陷阱](#7. 实战中的性能调优与常见陷阱)

1. 引言:为什么选择 Druid 作为数据库连接池?

Druid 作为阿里巴巴开源的数据库连接池,在现代应用开发中备受青睐,尤其在大规模生产环境中展现出显著优势。它不仅提供了高效的数据库连接管理,还内置了强大的监控和统计功能,能够帮助开发者深入理解数据库访问性能。

下面这个表格清晰地展示了 Druid 与其它常见数据库连接池的核心特性对比,您能直观地看到其优势所在:

特性 Druid HikariCP DBCP C3P0
性能 非常高 中等
监控功能 极其强大 基础 较弱
可扩展性 Filter-Chain模式,易于扩展 较弱 中等 中等
SQL防注入 内置WallFilter支持 不支持 不支持 不支持
生产环境验证 阿里巴巴大规模应用 广泛使用 广泛使用 广泛使用

核心优势解读

Druid 的优势体现在多个方面,使其在众多连接池中脱颖而出:

  • 全面的监控能力 :Druid 号称"为监控而生"。它的监控功能远超其他连接池,能够提供详尽的统计信息,例如 SQL执行的耗时区间分布 (帮助你清晰了解慢SQL的分布情况)、连接池的详细状态 (如活跃连接数、等待线程数等)以及 PSCache命中率 等关键指标。这为性能调优和故障排查提供了坚实的数据基础。

  • 卓越的性能与可扩展性 :Druid 在性能上表现优异,同时采用了 Filter-Chain 模式的插件体系 ,允许你像添加过滤器一样自定义功能,轻松实现性能监控、SQL审计、加密等需求。其内置的 ExceptionSorter 机制能快速识别并移除不可用的数据库连接,提升了系统的稳定性。

  • 企业级安全特性 :Druid 内置了 SQL防火墙(WallFilter),能够有效防御 SQL 注入攻击,这是很多其他连接池所不具备的重要安全特性。同时,它还支持对配置文件中的数据库密码进行加密,进一步增强了安全性。

  • 历经考验的稳定性:Druid 在阿里巴巴内部经历了大规模苛刻生产环境的长期考验,其稳定性和可靠性得到了充分验证。

2. Spring Boot 中集成 Druid 的基本步骤

在 Spring Boot 项目中集成 Druid 连接池,主要有两种主流方式:一种是使用官方提供的 druid-spring-boot-starter,这是目前最推荐、最便捷的方式;另一种是通过自定义配置类的方式,这种方式更传统,提供了更细粒度的控制。下面的表格清晰地展示了这两种方式的核心步骤和主要区别。

特性 使用官方 Starter (推荐) 自定义配置类
易用性 ,开箱即用 ,需要手动编写配置类
依赖管理 自动管理依赖和版本 需手动排除默认数据源(如 HikariCP)
配置方式 主要在 application.yml 中完成 需结合 application.yml 和 Java 配置类
灵活性 满足大部分场景 ,可进行高度定制
监控集成 通过配置属性轻松开启 需在配置类中手动注册 Servlet 和 Filter

2.1 方式一:使用官方 Starter(推荐)

这是当前最简单、最流行的集成方式,绝大多数项目都采用此法。

第1步:添加 Maven 依赖

在项目的 pom.xml 文件中添加 druid-spring-boot-starter 依赖。请注意,如果您的项目已经引入了 mybatis-spring-boot-starter 等包含默认数据源(HikariCP)的依赖,通常无需手动排除,因为 Druid Starter 的配置优先级更高。

xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.20</version> <!-- 请使用最新稳定版本 -->
</dependency>

第2步:配置 application.yml

这是核心步骤。您的配置示例正是采用了这种方式,关键在于 spring.datasource.druid 这个配置前缀。

第3步:验证集成

创建一个简单的测试类,检查数据源是否已成功切换为 Druid。

java 复制代码
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;

@SpringBootTest
class ApplicationTests {

    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() {
        System.out.println("当前数据源:" + dataSource.getClass().getName());
        // 输出应类似于:com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper
    }
}

完成以上步骤后,启动应用并访问 http://你的服务器地址/druid,即可看到Druid强大的监控后台。

2.2 方式二:自定义配置类(传统方式)

这种方式在早期Spring Boot版本中较常见,现在多用于需要深度定制的情况。

第1步:添加基本依赖

xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId> <!-- 注意,这里不是starter -->
    <version>1.2.20</version>
</dependency>

第2步:创建Druid配置类

通过 @Configuration 注解的配置类,手动将Druid数据源及其监控组件注册为Spring容器的Bean。

java 复制代码
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DruidConfig {

    // 将 application.yml 中 spring.datasource 前缀的配置绑定到DruidDataSource
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

    // 配置监控后台的Servlet
    @Bean
    public ServletRegistrationBean<StatViewServlet> statViewServlet() {
        ServletRegistrationBean<StatViewServlet> bean = 
            new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
        
        Map<String, String> initParams = new HashMap<>();
        initParams.put("loginUsername", "admin"); // 后台管理用户名
        initParams.put("loginPassword", "123456"); // 后台管理密码
        initParams.put("allow", ""); // 允许所有访问(IP白名单)
        // initParams.put("deny", "192.168.1.100"); // IP黑名单 (拒绝访问)
        
        bean.setInitParameters(initParams);
        return bean;
    }

    // 配置Web监控的Filter
    @Bean
    public FilterRegistrationBean<WebStatFilter> webStatFilter() {
        FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new WebStatFilter());
        
        Map<String, String> initParams = new HashMap<>();
        // 忽略静态资源和监控页面本身的请求
        initParams.put("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        bean.setInitParameters(initParams);
        bean.setUrlPatterns(Arrays.asList("/*")); // 拦截所有请求
        
        return bean;
    }
}

3. 连接池核心参数解析:从初始化到销毁

Druid 连接池的核心参数配置直接决定了数据库连接的性能、稳定性和资源利用率。

3.1 连接池大小配置

initial-size: 5

初始连接数,表示连接池启动时立即创建的连接数量。这就像停车点刚建成时,先投放5辆单车,确保有用户来时能立即使用,避免"冷启动"等待。

min-idle: 5

最小空闲连接数,连接池中始终保持的最小空闲连接数量。即使没有用户借车,停车点也要保留至少5辆单车,这样新用户来了就能直接骑走,无需等待调度。

maxActive: 50

最大活跃连接数,连接池能同时支持的最大连接数量。停车点最多只能容纳50辆单车,如果超过这个数量,新用户就需要排队等待。

maxWait: 60000

获取连接的最大等待时间(单位:毫秒)。当所有单车都被借走时,用户最多等待60秒,如果超时还没等到,就放弃借车(抛出异常)。

3.2 连接有效性检测

timeBetweenEvictionRunsMillis: 60000

检测间隔时间,每隔60秒检查一次连接池中的空闲连接。就像停车点管理员每隔1小时巡视一次,检查哪些单车长时间没人用,可能需要维修或回收。

minEvictableIdleTimeMillis: 300000

连接最小生存时间,空闲连接超过5分钟(300秒)后,如果连接池中的连接数超过min-idle,这些"超时"连接会被回收。这相当于停车点规定:如果某辆单车连续5分钟没人使用,且停车点单车总数超过5辆,就把它运回仓库。

validationQuery: SELECT 1

连接有效性检测SQL,用于检查连接是否可用。就像管理员每次借车前,会检查单车刹车是否正常(执行SELECT 1),确保安全。

validationQueryTimeout: 5

检测超时时间,执行validationQuery最多等待5秒,超时则认为连接不可用。

3.3 检测策略配置

testWhileIdle: true

空闲时检测,建议开启。当连接空闲时间超过timeBetweenEvictionRunsMillis时,自动执行validationQuery检测。这就像管理员在巡视时,会检查长时间没人用的单车是否还能正常使用。

最佳实践建议:将testWhileIdle设置为true,testOnBorrow和testOnReturn设置为false,可以在不影响性能的前提下保证连接有效性。

testWhileIdle 只是 Druid 的"空闲时检测"开关,把它从 false 改成 true 后,连接池会周期性地把当前池里空闲 的连接拿出来执行一条探活 SQL(默认 SELECT 1)。如果探活失败就会把这条连接丢弃并新建,从而保证:

  1. 连接在真正被业务线程借出去之前,大概率已经被验证过,不会拿到"僵尸连接";
  2. 对 MySQL 来说,这条探活 SQL 也算一次通讯,会把 wait_timeout 的空闲计时器清零,避免服务端把连接杀掉。

testOnBorrow: false

借出时检测,默认关闭。每次借出连接时都检测,会降低性能。就像每次借车前都要检查刹车,虽然安全但效率低。

testOnReturn: false

归还时检测,默认关闭。每次归还连接时检测,同样影响性能。就像每次还车都要检查单车是否损坏,没必要。

3.4 连接池参数配置建议

参数 推荐值 说明
initial-size 5-10 根据应用启动时的并发量调整
min-idle 5-10 保持一定数量的"热连接"
maxActive 20-100 根据数据库性能和业务并发量调整
maxWait 30000-60000 避免长时间等待导致请求超时
timeBetweenEvictionRunsMillis 60000 每分钟检测一次
minEvictableIdleTimeMillis 300000 5分钟空闲后回收

4. 监控配置揭秘:StatViewServlet 与 WebStatFilter

Druid 最强大的特性之一就是其内置的监控功能,它通过两个核心组件实现:StatViewServletWebStatFilter。这两个组件就像连接池的"眼睛"和"耳朵",分别负责展示监控数据和收集统计信息。

4.1 StatViewServlet:监控页面的"展示窗口"

StatViewServlet 是 Druid 提供的监控后台,通过 Web 页面展示连接池的详细状态信息。它就像连接池的"仪表盘",让你可以实时查看各项指标。

核心配置参数

yaml 复制代码
spring:
  datasource:
    druid:
      stat-view-servlet:
        enabled: true              # 启用监控页面
        url-pattern: /druid/*      # 访问路径
        login-username: admin      # 登录用户名
        login-password: 123456     # 登录密码
        allow:                     # IP白名单,空表示允许所有
        reset-enable: false        # 是否允许重置统计数据

监控页面功能详解

启动应用后,访问 http://localhost:8080/druid(根据实际端口调整),输入配置的用户名和密码,即可看到以下核心功能:

1. 数据源页面

  • 活跃连接数:当前正在使用的连接数量
  • 池中连接数:连接池中总连接数
  • 等待线程数:正在等待获取连接的线程数
  • 最大活跃连接数 :历史最大活跃连接数

2. SQL监控页面

  • 执行次数:每条SQL的执行次数
  • 执行时间:总执行时间、最大执行时间、平均执行时间
  • 慢SQL统计:执行时间超过阈值的SQL(默认5000ms)
  • 执行时间分布:0-1ms、1-10ms、10-100ms、100-1000ms、1-10s、10s+ 的分布情况

3. Web应用页面

  • URI访问统计:每个URI的访问次数、执行时间
  • Session监控:活跃Session数量、创建时间
  • JVM监控 :堆内存、非堆内存、GC次数

4.2 WebStatFilter:统计数据的"收集器"

WebStatFilter 负责收集 Web 应用的访问统计信息,包括 URI 访问次数、执行时间、Session 信息等。它就像连接池的"耳朵",监听所有 Web 请求。

核心配置参数

yaml 复制代码
spring:
  datasource:
    druid:
      web-stat-filter:
        enabled: true
        url-pattern: "/*"           # 拦截所有请求
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"  # 排除静态资源
        session-stat-enable: true   # 启用Session统计
        session-stat-max-count: 1000 # 最大Session统计数量

配置参数详解

exclusions:需要排除统计的请求,通常包括:

  • 静态资源:*.js,*.gif,*.jpg,*.png,*.css,*.ico
  • 监控页面本身:/druid/*
  • 健康检查接口:/actuator/health

session-stat-enable:是否启用 Session 统计,建议开启以监控用户会话状态。

session-stat-max-count:最大 Session 统计数量,避免内存溢出。

4.5 监控页面访问

启动应用后,访问 http://localhost:8080/druid(根据实际端口调整),输入配置的用户名和密码,即可看到完整的监控界面。

关键建议

  1. 生产环境必须配置安全措施:设置强密码、限制IP访问、禁止重置数据
  2. 定期查看监控数据:重点关注慢SQL、连接池状态、内存使用情况
  3. 根据监控数据调优 :如果发现连接池频繁达到最大连接数,需要调整 max-active 参数;如果发现大量慢SQL,需要优化SQL语句或添加索引

Druid 过滤器链是其架构设计的精髓所在,它通过责任链模式为数据库操作提供了强大的可扩展性。您配置中的 filters: stat,wall,slf4j 正是启用了三个核心过滤器,它们各自扮演着独特的角色。下面这个表格清晰地展示了这三者的分工。

过滤器 核心职责 好比...
StatFilter 性能监控官:统计 SQL 执行次数、耗时、连接池状态等指标。 高速公路的测速摄像头和车流量统计系统,记录每辆车的速度、车型和通行时间。
WallFilter 安全守卫:基于 SQL 语义分析防御 SQL 注入攻击,强制执行安全策略。 高速公路的安检站和交通法规,检查车辆是否携带违禁品,是否遵守通行规则(如禁止货车通行)。
Slf4jLogFilter 审计记录员:将 SQL 执行相关的日志输出到 SLF4J 接口,便于集成日志框架。 收费站的通行记录仪,详细记录每一笔交易(SQL执行)的细节,用于对账和复查。

5. 过滤器链:stat、wall、slf4j 的作用与原理

5.1 StatFilter:性能监控的基石

StatFilter 是 Druid 监控功能的数据来源,它负责收集所有关键的性能指标。

工作原理

StatFilter 通过代理(Proxy)机制,在 JDBC 驱动的 Connection, Statement, ResultSet 等对象的关键方法(如 execute, close)执行前后插入拦截点。在这些拦截点中,它会记录方法调用的开始时间和结束时间,从而计算出执行耗时,并累加执行次数。

核心配置(通常在 application.yml 中)

您配置中的 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 就与 StatFilter 密切相关。

yaml 复制代码
spring:
  datasource:
    druid:
      filter:
        stat:
          enabled: true # 启用StatFilter
          log-slow-sql: true # 开启慢SQL记录
          slow-sql-millis: 5000 # 定义慢SQL阈值,单位毫秒
          merge-sql: true # 合并相似SQL(如SELECT * FROM user WHERE id = ?),便于统计

这些统计数据最终会在 Druid 的监控页面(如 SQL监控数据源页面)上直观地展示出来。

5.2 WallFilter:SQL 防火墙

WallFilter 是 Druid 提供的企业级安全特性,它通过内置的 SQL 语法解析器对执行的 SQL 进行实时分析,而非简单的字符串匹配,从而有效防御 SQL 注入攻击。

防御策略

WallFilter 维护了一套详尽的安全策略(WallConfig),主要包括:

  • 语法检查 :检测是否使用了永真条件(如 1=1)、注释等可疑语法。
  • 对象检查 :是否引用了禁止访问的表(tableCheck)或模式(schemaCheck)。
  • 行为控制 :是否可以执行 DELETEUPDATE 不带 WHERE 子句等危险操作。您甚至可以配置一个只读数据源,禁止任何数据修改语句。

配置示例

yaml 复制代码
spring:
  datasource:
    druid:
      filter:
        wall:
          enabled: true
          config:
            delete-allow: false # 是否允许删除语句
            drop-table-allow: false # 是否允许删表操作,生产环境应严格关闭
            # 更多精细策略,如指定只读表
            read-only-tables: config_table, audit_log

当检测到违规 SQL 时,WallFilter 默认会抛出 SQLException 中止执行,从而保护数据库。你可以在监控页面的 SQL防火墙 标签页查看拦截信息。

5.3 Slf4jLogFilter:可定制的日志输出

Slf4jLogFilter 充当了数据库操作与应用程序日志系统(如 Logback、Log4j2)之间的桥梁。它将 SQL 执行信息输出到日志文件,方便开发调试和问题追踪。

高度可配置的日志内容

与 StatFilter 聚焦于聚合统计不同,Slf4jLogFilter 更关注单次执行的详细信息,并且可以按需开启或关闭特定日志。

yaml 复制代码
spring:
  datasource:
    druid:
      filter:
        slf4j:
          enabled: true
          statement-executable-sql-log-enable: true # 关键配置:在日志中打印出可执行的(带参数的)完整SQL
          # 以下选项提供了更细粒度的控制
          statement-create-after-log-enabled: false # 记录Statement创建日志(通常不需要)
          statement-close-after-log-enabled: false # 记录Statement关闭日志
          result-set-open-after-log-enabled: false # 记录ResultSet打开日志

启用 statement-executable-sql-log-enable 后,在你的应用日志中可能会看到这样的输出,这对于调试非常有帮助:

复制代码
[Druid-ConnectionPool-Log-Thread] INFO  c.a.d.filter.logging.Slf4jLogFilter - 
Executable SQL: SELECT * FROM user WHERE name = '张三' AND age > 18

5.4 过滤器链的工作流程与扩展

链式调用

当应用程序通过 Druid 执行一条 SQL 时,请求会依次经过配置的过滤器链。例如,一条 SELECT 语句会先经过 WallFilter 的安全检查 ,然后由 StatFilter 记录耗时和次数 ,最后通过 Slf4jLogFilter 打印详细日志。这种设计使得每个过滤器职责单一,且易于扩展。

自定义过滤器

Druid 的过滤器链是开放的。你可以通过实现 com.alibaba.druid.filter.Filter 接口或继承 FilterAdapter 类,并重写相关方法(如 statementExecuteBefore, statementExecuteAfter)来创建自定义过滤器,实现诸如分库分表路由、数据加解密等高级功能。

6. 高级特性:PSCache 与连接属性配置

Druid 除了基础的连接池功能外,还提供了一些高级特性,这些特性能够显著提升数据库访问性能并提供更细致的监控能力。您配置中的 poolPreparedStatementsconnectionProperties 正是这些高级特性的体现。

6.1 PSCache:预编译语句缓存

PSCache(PreparedStatement Cache)是 Druid 中的一个重要性能优化特性,它通过缓存预编译的 SQL 语句来提升数据库访问效率。

什么是 PreparedStatement?

在了解 PSCache 之前,先简单了解 PreparedStatement:

java 复制代码
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

// 不使用 PreparedStatement
String sql1 = "SELECT * FROM users WHERE id = " + userId; // 有SQL注入风险

// 使用 PreparedStatement
String sql2 = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql2);
pstmt.setInt(1, userId);
ResultSet rs = pstmt.executeQuery();

PSCache 的工作原理

没有 PSCache 的情况

  1. 每次执行 SQL 时,都需要创建新的 PreparedStatement 对象
  2. 数据库每次都需要重新解析和编译 SQL
  3. 创建和销毁 PreparedStatement 对象带来额外开销

启用 PSCache 的情况

  1. PreparedStatement 对象被缓存起来
  2. 下次执行相同 SQL 时,直接使用缓存的 PreparedStatement
  3. 只需设置参数即可执行,无需重新编译

核心配置参数

yaml 复制代码
spring:
  datasource:
    druid:
      # 启用PSCache
      poolPreparedStatements: true
      # 每个连接上PSCache的大小
      maxPoolPreparedStatementPerConnectionSize: 100

参数详解

poolPreparedStatements: true

启用 PSCache 功能。当设置为 true 时,Druid 会缓存每个连接上的 PreparedStatement 对象。

maxPoolPreparedStatementPerConnectionSize: 100

每个数据库连接最多缓存的 PreparedStatement 数量。这个值不宜设置过大,通常 20-100 是比较合理的范围。

PSCache 的优缺点

优点

  1. 性能提升:避免重复编译 SQL,提高执行效率
  2. 资源复用:复用 PreparedStatement 对象,减少内存分配
  3. 减少数据库负载:数据库无需重复解析相同 SQL

缺点

  1. 内存占用:每个缓存的 PreparedStatement 都会占用内存
  2. 连接隔离:缓存是连接级别的,不同连接之间不共享
  3. SQL 差异:只有完全相同的 SQL 才会被缓存

7. 实战中的性能调优与常见陷阱

在掌握了 Druid 的各项配置后,如何将这些知识应用到实际项目中,避免常见的性能问题和配置陷阱,是每个开发者都需要面对的挑战。本章将结合实战经验,为您提供一套完整的性能调优方案和常见问题的解决方案。

连接池大小的配置直接影响系统性能,过大或过小都会带来问题。黄金法则:连接池大小 = (核心数 * 2) + 有效磁盘数。

调优步骤

  1. 初始配置:基于业务场景设置初始值

    yaml 复制代码
    initial-size: 10
    min-idle: 10
    max-active: 50
  2. 监控观察:通过 Druid 监控页面观察以下指标:

    • 活跃连接数是否经常达到 max-active
    • 等待线程数是否频繁出现
    • 连接获取时间是否过长
  3. 动态调整

    • 如果活跃连接数经常达到 max-active,且等待线程数较多,适当增大 max-active
    • 如果活跃连接数远小于 max-active,且 min-idle 连接长时间空闲,适当减小配置

生产环境建议

  • 对于 OLTP 系统:max-active 建议 20-100
  • 对于 OLAP 系统:max-active 建议 50-200
  • 对于批处理任务:根据并发度调整

完整示例

yml 复制代码
datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: admin
        url-pattern: /druid/*
        allow:
      web-stat-filter:
        enabled: true
    dynamic:
      druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
        # 连接池的配置信息
        # 初始化大小,最小,最大
        initial-size: 5
        min-idle: 5
        maxActive: 50
        # #获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
        maxWait: 60000
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        timeBetweenEvictionRunsMillis: 60000
        # 配置一个连接在池中最小生存的时间,单位是毫秒
        minEvictableIdleTimeMillis: 300000
        # 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用
        validationQuery: SELECT 1
        validationQueryTimeout: 5
        #建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
        testWhileIdle: true
        #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
        testOnBorrow: false
        #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
        testOnReturn: false
        # 打开PSCache,并且指定每个连接上PSCache的大小
        poolPreparedStatements: true
        #要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
        maxPoolPreparedStatementPerConnectionSize: 100
        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat,wall,slf4j
        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      datasource:
        master:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/database?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
          username: admin	
          password: admin
相关推荐
学Linux的语莫2 小时前
mysql主从同步(复制)搭建
数据库·mysql
SelectDB2 小时前
慢 SQL 诊断准确率 99.99%,天翼云基于 Apache Doris MCP 的 AI 智能运维实践
数据库·人工智能·apache
JIngJaneIL2 小时前
基于java+ vue交友系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·交友
苹果酱05672 小时前
解决linux mysql命令 bash: mysql: command not found 的方法
java·vue.js·spring boot·mysql·课程设计
程序员飞哥2 小时前
这样做的幂等也太全了吧
java·后端·spring
虫小宝2 小时前
返利软件架构设计:多平台适配的抽象工厂模式实践
java·开发语言·抽象工厂模式
数据知道2 小时前
为什么要用向量数据库?常用的向量数据库有哪些以及如何选择?
数据库·向量数据库
dixiuapp3 小时前
设备维修记录系统,从数据沉淀到价值挖掘的跃迁
大数据·数据库·人工智能