前言
作为后台服务开发,在日常工作中我们天天都在跟数据库打交道,一直在进行各种CRUD操作,都会使用到数据库连接池。按照发展历程,业界知名的数据库连接池有以下几种:c3p0、DBCP、Tomcat JDBC Connection Pool、Druid 等。
HiKariCP 号称是业界跑得最快的数据库连接池,自从 SpringBoot 2.0 将其作为默认数据库连接池。
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
1、什么是数据库连接池
就是一个容器持有多个数据库连接,当程序需要操作数据库的时候直接从池中取出连接,使用完之后再还回去,和线程池一个道理。
从根本上而言,数据库连接池和我们常用的线程池一样,都属于池化资源,它在程序初始化时创建一定数量的数据库连接对象并将其保存在一块内存区中。它允许应用程序重复使用一个现有的数据库连接,当需要执行 SQL 时,我们是直接从连接池中获取一个连接,而不是重新建立一个数据库连接,当 SQL 执行完,也并不是将数据库连接真的关掉,而是将其归还到数据库连接池中。我们可以通过配置连接池的参数来控制连接池中的初始连接数、最小连接、最大连接、最大空闲时间等参数,来保证访问数据库的数量在一定可控制的范围类,防止系统崩溃,同时保证用户良好的体验。数据库连接池示意图如下所示:
因此使用数据库连接池的核心作用,就是避免数据库连接频繁创建和销毁,节省系统开销。因为数据库连接是有限且代价昂贵,创建和释放数据库连接都非常耗时,频繁地进行这样的操作将占用大量的性能开销,进而导致网站的响应速度下降,甚至引起服务器崩溃。
2、为什么需要连接池
- 节省资源,如果每次访问数据库都创建新的连接,创建和销毁都浪费系统资源。
- 响应性更好,省去了创建的时间,响应性更好。
- 统一管理数据库连接,避免因为业务的膨胀导致数据库连接的无限增多。
- 便于监控。
3、常见数据库连接池对比分析
这里详细总结了常见数据库连接池的各项功能比较,我们重点分析下当前主流的阿里巴巴 Druid 与 HikariCP,HikariCP 在性能上是完全优于 Druid 连接池的。而 Druid 的性能稍微差点是由于锁机制的不同,并且 Druid 提供更丰富的功能,包括监控、sql拦截与解析等功能,两者的侧重点不一样,HikariCP追求极致的高性能。
在性能上面这五种数据库连接池的排序如下:
HikariCP > druid > tomcat-jdbc > dbcp > c3p0:
4、SpringBoot 整合 Druid
① 在pom.xml中引入druid官方提供的Spring Boot Starter封装
注意:此包1.1.10后的版本数据监控中心做了调整需要自己新增配置类
<!--druid数据源 1.1.21 此版本的数据监控中心增加了登录界面需要增加配置类-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
② 在application.properties中配置数据库连接信息
Druid的配置都以spring.datasource.druid作为前缀
#数据库连接中修改数据源类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
# 测试连接
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
# 配置监控统计拦截的filters
# asyncInit是1.1.4中新增加的配置,如果有initialSize数量较多时,打开会加快应用启动时间
spring.datasource.asyncInit=true
# druid监控配置信息
spring.datasource.filters=stat,config
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.useGlobalDataSourceStat=true
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
5、配置 Druid 监控
① 在pom.xml中引入spring-boot-starter-actuator模块
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
② 配置文件中添加Druid的监控配置,主要用于开启stat监控统计的界面以及监控内容的相关配置
spring.datasource.druid.stat-view-servlet.enabled=true
# 访问地址规则
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
# 是否允许清空统计数据
spring.datasource.druid.stat-view-servlet.reset-enable=true
# 监控页面的登录账户
spring.datasource.druid.stat-view-servlet.login-username=admin
# 监控页面的登录密码
spring.datasource.druid.stat-view-servlet.login-password=admin
③ 访问页面
完成上面所有配置之后,启动应用,访问Druid的监控页面 http://localhost:项目端口号/druid/
输入配置的
- spring.datasource.druid.stat-view-servlet.login-username=admin
- spring.datasource.druid.stat-view-servlet.login-password=admin
配置的登录账户与密码,就能看到监控页面。
6、Druid 打印完整 SQL
# 打印完整SQL
logging.level.druid.sql.Statement=debug
spring.datasource.druid.filter.slf4j.enabled=true
spring.datasource.druid.filter.slf4j.statementPrepareAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementCreateAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteQueryAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementParameterSetLogEnabled=false
spring.datasource.druid.filter.slf4j.statementCloseAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteBatchAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteUpdateAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementPrepareCallAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecutableSqlLogEnable=true
spring.datasource.druid.filter.slf4j.statementLogEnabled=true