根据综合性能,可靠性,稳定性,扩展性,易用性等因素替换成最优的数据库连接池。

Druid:druid-1.0.29

数据库  Mysql.5.6.17

替换目标:替换掉C3P0,用druid来替换

替换原因:

1、性能方面 hikariCP>druid>tomcat-jdbc>dbcp>c3p0 。hikariCP的高性能得益于最大限度的避免锁竞争。

2、druid功能最为全面,sql拦截等功能,统计数据较为全面,具有良好的扩展性。

3、综合性能,扩展性等方面,可考虑使用druid或者hikariCP连接池,比较方便对jdbc接口进行监控跟踪等。

4、可开启prepareStatement缓存,对性能会有大概20%的提升。

  • psCache是connection私有的,所以不存在线程竞争的问题,开启pscache不会存在竞争的性能损耗。
  • psCache的key为prepare执行的sql和catalog等,value对应的为prepareStatement对象。开启缓存主要是减少了解析sql的开销。

5、3p0历史悠久,代码及其复杂,不利于维护。并且存在deadlock的潜在风险。

6、Druid可以打印SQL,慢查询方面的日志

Druid 参数

配置参数

缺省值

游戏服设置的值

参数说明

initialSize

0

4

初始化连接数量

minIdle

0

4

最小空闲连接数

maxActive

8

8

最大并发连接数

maxWait

-1L

60000

获取连接时最大等待时间,单位毫秒。配置了maxWait之后,

缺省启用公平锁,并发效率会有所下降,

如果需要可以通过配置useUnfairLock属性为true使用非公平锁。

timeBetweenEvictionRunsMillis

60000

60000

配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

Destroy线程会检测连接的间隔时间

minEvictableIdleTimeMillis

1800000

1800000

配置一个连接在池中最小生存的时间,单位是毫秒

validationQuery

null

select 1

用来检测连接是否有效的sql,要求是一个查询语句

testOnBorrow

FALSE

FALSE

申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

testOnReturn

FALSE

FALSE

归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能

testWhileIdle

TRUE

TRUE

建议配置为true,不影响性能,并且保证安全性。 申请连接的时候检测,如果

空闲时间大于 timeBetweenEvictionRunsMillis, 执行validationQuery检测连接是否有效。

poolPreparedStatements

FALSE

TRUE

false 是否缓存preparedStatement,也就是PSCache。

PSCache对支持游标的数据库性能提升巨大,比如说oracle。

在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。

5.5及以上版本有PSCache,建议开启。

maxPoolPreparedStatementPerConnectionSize

10

100

要启用PSCache,必须配置大于0,当大于0时,

poolPreparedStatements自动触发修改为true。

单个connnection独享一个statement cache,也就是说maxOpenPreparedStatements是针对单个connection链接的




validationQuery和testWhileIdle这两个参数一起用,用来不间断检测是否有失效的链接,避免高并发的出现失效链接;

DataBase

validationQuery

hsqldb

select 1 from INFORMATION_SCHEMA.SYSTEM_USERS

Oracle

select 1 from dual

DB2

select 1 from sysibm.sysdummy1

MySql

select 1

Microsoft SqlServer

select1

postgresql

select version()

ingres

select 1

derby

values 1

H2

select 1





运行原理:


数据库连接池在初始化的时候会创建initialSize个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过了maxWait,则会报错;如果当前正在使用的连接数没有达到maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。 同时连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某个连接在空闲了timeBetweenEvictionRunsMillis时间后仍然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个testWhileIdle参数为true,可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的Connection对象是可用的。当然,为了保证绝对的可用性,你也可以使用testOnBorrow为true(即在获取Connection对象时检测其可用性),不过这样会影响性能。


Log4j2Filter log4j2 = new Log4j2Filter();
log4j2.setResultSetLogEnabled(false);
log4j2.setStatementSqlPrettyFormat(false);
log4j2.setStatementExecutableSqlLogEnable(true);

log4j2.setDataSourceLogEnabled(false);
log4j2.setConnectionLogEnabled(false);
log4j2.setStatementLogEnabled(false);
log4j2.setResultSetLogEnabled(false);
ret.setProxyFilters(Arrays.asList(log4j2));

闲置检测,创建连接,废弃连接清理由这三线程管理

Daemon Thread [Abandoned connection cleanup thread]
Daemon Thread [Druid-ConnectionPool-Create-1184124073] 
Daemon Thread [Druid-ConnectionPool-Destroy-1184124073] 


步骤:

  1. 导入依赖
<!-- 连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
</dependency>

2.配置

<!-- 加载配置属性文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:cfg.properties" />

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
    <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
    <property name="driverClassName" value="${jdbc.driver}" />

    <!-- 基本属性 url、user、password -->
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />

    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="${jdbc.pool.init}" />
    <property name="minIdle" value="${jdbc.pool.minIdle}" /> 
    <property name="maxActive" value="${jdbc.pool.maxActive}" />

    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000" />

    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />

    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000" />

    <property name="validationQuery" value="${jdbc.testSql}" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="false" />
    <property name="testOnReturn" value="false" />

    <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用)
    <property name="poolPreparedStatements" value="true" />
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->

    <!-- 配置监控统计拦截的filters -->
    <property name="filters" value="stat" /> 
</bean>
jdbc.type=mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

#pool settings
jdbc.pool.init=1
jdbc.pool.minIdle=3
jdbc.pool.maxActive=20

#jdbc.testSql=SELECT 1
jdbc.testSql=SELECT 1

3.配置druid的servlet

<servlet>
      <servlet-name>DruidStatView</servlet-name>
      <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
      <servlet-name>DruidStatView</servlet-name>
      <url-pattern>/druid/*</url-pattern>
</servlet-mapping>

4.配置登录监控的用户名和密码

<!-- 配置 Druid 监控信息显示页面 -->  
<servlet>  
    <servlet-name>DruidStatView</servlet-name>  
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  
    <init-param>  
    <!-- 允许清空统计数据 -->  
    <param-name>resetEnable</param-name>  
    <param-value>true</param-value>  
    </init-param>  
    <init-param>  
    <!-- 用户名 -->  
    <param-name>loginUsername</param-name>  
    <param-value>druid</param-value>  
    </init-param>  
    <init-param>  
    <!-- 密码 -->  
    <param-name>loginPassword</param-name>  
    <param-value>druid</param-value>  
    </init-param>  
</servlet>  
<servlet-mapping>  
    <servlet-name>DruidStatView</servlet-name>  
    <url-pattern>/druid/*</url-pattern>  
</servlet-mapping>

5.配置allow和deny
StatViewSerlvet展示出来的监控信息比较敏感,是系统运行的内部情况,如果你需要做访问控制,可以配置allow和deny这两个参数。比如:

<servlet>
      <servlet-name>DruidStatView</servlet-name>
      <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
    <init-param>
        <param-name>allow</param-name>
        <param-value>127.0.0.1</param-value>
    </init-param>
    <init-param>
        <param-name>deny</param-name>
        <param-value>128.242.127.4</param-value>
    </init-param>
</servlet>

判断规则: deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝。如果allow没有配置或者为空,则允许所有访问。

注意: 由于匹配规则不支持IPV6,配置了allow或者deny之后,会导致IPV6无法访问

6.配置resetEnable
在StatViewSerlvet输出的html页面中,有一个功能是Reset All,执行这个操作之后,会导致所有计数器清零,重新计数。你可以通过配置参数关闭它。

<servlet>
    <servlet-name>DruidStatView</servlet-name>
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
  <init-param>
     <param-name>resetEnable</param-name>
     <param-value>false</param-value>
  </init-param>
</servlet>

7.访问就可以了

http://localhost:8081/myprogram/druid/


根据综合性能,可靠性,稳定性,扩展性,易用性等因素替换成最优的数据库连接池。

Druid:druid-1.0.29

数据库  Mysql.5.6.17

替换目标:替换掉C3P0,用druid来替换

替换原因:

1、性能方面 hikariCP>druid>tomcat-jdbc>dbcp>c3p0 。hikariCP的高性能得益于最大限度的避免锁竞争。

2、druid功能最为全面,sql拦截等功能,统计数据较为全面,具有良好的扩展性。

3、综合性能,扩展性等方面,可考虑使用druid或者hikariCP连接池,比较方便对jdbc接口进行监控跟踪等。

4、可开启prepareStatement缓存,对性能会有大概20%的提升。

  • psCache是connection私有的,所以不存在线程竞争的问题,开启pscache不会存在竞争的性能损耗。
  • psCache的key为prepare执行的sql和catalog等,value对应的为prepareStatement对象。开启缓存主要是减少了解析sql的开销。

5、3p0历史悠久,代码及其复杂,不利于维护。并且存在deadlock的潜在风险。

6、Druid可以打印SQL,慢查询方面的日志

Druid 参数

配置参数

缺省值

游戏服设置的值

参数说明

initialSize

0

4

初始化连接数量

minIdle

0

4

最小空闲连接数

maxActive

8

8

最大并发连接数

maxWait

-1L

60000

获取连接时最大等待时间,单位毫秒。配置了maxWait之后,

缺省启用公平锁,并发效率会有所下降,

如果需要可以通过配置useUnfairLock属性为true使用非公平锁。

timeBetweenEvictionRunsMillis

60000

60000

配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

Destroy线程会检测连接的间隔时间

minEvictableIdleTimeMillis

1800000

1800000

配置一个连接在池中最小生存的时间,单位是毫秒

validationQuery

null

select 1

用来检测连接是否有效的sql,要求是一个查询语句

testOnBorrow

FALSE

FALSE

申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

testOnReturn

FALSE

FALSE

归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能

testWhileIdle

TRUE

TRUE

建议配置为true,不影响性能,并且保证安全性。 申请连接的时候检测,如果

空闲时间大于 timeBetweenEvictionRunsMillis, 执行validationQuery检测连接是否有效。

poolPreparedStatements

FALSE

TRUE

false 是否缓存preparedStatement,也就是PSCache。

PSCache对支持游标的数据库性能提升巨大,比如说oracle。

在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。

5.5及以上版本有PSCache,建议开启。

maxPoolPreparedStatementPerConnectionSize

10

100

要启用PSCache,必须配置大于0,当大于0时,

poolPreparedStatements自动触发修改为true。

单个connnection独享一个statement cache,也就是说maxOpenPreparedStatements是针对单个connection链接的




validationQuery和testWhileIdle这两个参数一起用,用来不间断检测是否有失效的链接,避免高并发的出现失效链接;

DataBase

validationQuery

hsqldb

select 1 from INFORMATION_SCHEMA.SYSTEM_USERS

Oracle

select 1 from dual

DB2

select 1 from sysibm.sysdummy1

MySql

select 1

Microsoft SqlServer

select1

postgresql

select version()

ingres

select 1

derby

values 1

H2

select 1





运行原理:


数据库连接池在初始化的时候会创建initialSize个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过了maxWait,则会报错;如果当前正在使用的连接数没有达到maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。 同时连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某个连接在空闲了timeBetweenEvictionRunsMillis时间后仍然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个testWhileIdle参数为true,可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的Connection对象是可用的。当然,为了保证绝对的可用性,你也可以使用testOnBorrow为true(即在获取Connection对象时检测其可用性),不过这样会影响性能。