https://www.mchange.com/projects/c3p0/apidocs/index.html
c3p0是一个库。它扩展了传统的jdbc数据库连接池,并且支持JDBC3规范和JDBC2的标准扩展。
普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。
C3P0连接池默认在缓冲池里面防放置一定数量的连接(initialPoolSize) , 当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
c3p0与dbcp是比较常用的两种连接池,他两的区别在于:dbcp没有自动回收空闲连接的功能,c3p0有自动回收空闲连接功能
连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时, 并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次 数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等
准备所需的jar包:
c3p0-0.9.5.2.jar
mysql-connector-java-5.1.45.jar
ojdbc8.jar 【由于JDK版本不同,所需要的jar不同,此jar包适用于JDK1.8】
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="mysql">
<!-- 配置数据库用户名 -->
<property name="user">root</property>
<!-- 配置数据库密码 -->
<property name="password">你的数据库密码</property>
<!-- 配置数据库链接地址 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/这里是你的数据库名?useUnicode=true&characterEncoding=UTF-8</property>
<!-- 配置数据库驱动 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!-- 初始化连接数 -->
<property name="initialPoolSize">3</property>
<!-- 最小连接数 -->
<property name="minPoolSize">3</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">15</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:0 -->
<property name="maxStatements">0</property>
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
<property name="maxStatementsPerConnection">0</property>
<!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能 通过多线程实现多个操作同时被执行。Default:3 -->
<property name="numHelperThreads">3</property>
<!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->
<property name="propertyCycle">3</property>
<!-- 获取连接超时设置 默认是一直等待单位毫秒 -->
<property name="checkoutTimeout">1000</property>
<!--每多少秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">3</property>
<!--最大空闲时间,多少秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">10</property>
<!--配置连接的生存时间,超过这个时间的连接将由连接池自动断开丢弃掉。当然正在使用的连接不会马上断开,而是等待它close再断开。配置为0的时候则不会对连接的生存时间进行限制。 -->
<property name="maxIdleTimeExcessConnections">5</property>
<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试使用。Default: null -->
<property name="automaticTestTable">Test</property>
<!-- 获取connnection时测试是否有效 -->
<property name="testConnectionOnCheckin">true</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">3</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">30</property>
<!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
<property name="acquireRetryDelay">1000</property>
</named-config>
</c3p0-config>
- 拷贝C3P0所需的jar包到lib下
- 创建c3p0-config.xml,该文件需要放在classpath路径下,即src目录下,创建c3p0连接池.
ComboPooledDataSource DataSource = new ComboPooledDataSource();
Connection connection = DataSource.getConnection();
connection.close();
分类 | 属性 | 描述 |
必须项 | driverClass | 驱动类名 |
jdbcUrl | 连接地址 | |
user | 用户名 | |
password | 密码 | |
基本配置 | acquireIncrement | 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 |
acquireRetryAttempts | 定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 | |
maxIdleTime | 最大空闲时间,若为0则永不丢弃。Default: 0 | |
maxPoolSize | 连接池中保留的最大连接数。Default: 15 | |
MinPoolSize | 连接池中保留的最小连接数,默认为:3 | |
initialPoolSize | 初始化连接池中的连接数,取值应在minPoolSiz与maxPoolSize之间,默认为3 | |
可选择配置项 | acquireRetryDelay | 两次连接中间隔时间,单位毫秒。Default: 1000 |
autoCommitOnClose | 连接关闭时默认将所有未提交的操作回滚。Default: false | |
automaticTestTable | c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试 使用。Default: null | |
idleConnectionTestPeriod | C3P0会有一个Task检测pool内的连接是否正常,此参数就是Task运行的频率。默认值为0,表示不进行检测 | |
maxStatements | JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。 如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 | |
maxStatementsPerConnection | maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 | |
numHelperThreads | c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能 通过多线程实现多个操作同时被执行。Default: 3 | |
preferredTestQuery | 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意: 测试的表必须在初始数据源的时候就存在。Default: null | |
checkoutTimeout | 当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出 SQLException,如设为0则无限期等待。单位毫秒。Default: 0 | |
不建议配置项 | breakAfterAcquireFailure | 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default: false |
testConnectionOnCheckout | true表示在每次从pool内checkout连接的时候测试其有效性,这是个同步操作,因此应用端的每次数据库调用,都会先通过测试sql测试其有效性,如果连接无效,会关闭此连接并剔除出pool,并尝试从pool内取其他连接,默认为false,此特性要慎用,会造成至少多一倍的数据库调用 | |
testConnectionOnCheckin | true表示每次把连接checkin到pool里的时候测试其有效性,因为是个事后操作,所以是异步的,应用端不需要等待测试结果,但同样会造成至少多一倍的数据库调用 |
1:c3p0连接数据库
ComboPooledDataSource 为数据库链接池,用来管理数据库链接的获取和存储 。
新建一个数据源,new ComboPooledDataSource ();此操作会根据配置文件初始化连接池,根据 initialPoolSize 设置的值,加载相应的数据库连接到池中 。客户端可通过getConnettion()方法从连接池获取连接
2:如果初始化连接池失败会根据 acquireIncrement ( 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 ), acquireRetryAttempts ( 从数据库获取新连接失败后重复尝试的次数 ), acquireRetryDelay ( 两次连接中间隔时间 )这三个参数去重新获取连接,【由于数据库有设置比如登录验证失败次数,当c3p0重复获取连接次数超过数据库允许次数,数据库会锁定用户】
3:c3p0获取连接失败 ,参数 breakAfterAcquireFailure 为 true表示pool向数据库请求连接失败后标记整个pool为block并close,就算后端数据库恢复正常也不进行重连,客户端对pool的请求都拒绝掉。false表示不会标记 pool为block,新的请求都会尝试去数据库请求connection。默认为false。因此,如果想让数据库和网络故障恢复之后,pool能继续请求正常资源必须把此项配置设为false
4:c3p0初始化连接池成功, 获取ds.getConnection()链接对象时,内部使用getPoolManger()获取C3p0ConnectionPooledManager(mgr)对象,该manager管理着pool对象:C3P0PooledConnectionPo对象,mgr.getPool().checkoutPooledConnection() 会从连接池获取一个处于空闲状态的连接,客户端用完该链接后,该链接会被线程池回收,当下次客户端调用的时候还能接着用,这样减少了每次调用都从数据源获取连接造成的资源浪费。c3p0在从连接池中获取和返回连接的时候,采用了异步的处理方式,使用一个线程池来异步的 把返回关闭了(没有真正关闭)的连接放入连接池中。这样就意味着,我们在调用了从c3p0获得的连接的close方法时,不是立即放回池中的,而是放入一 个事件队列中等待c3p0内部的线程池顺序的处理。
5:当c3p0连接池的初始化连接数被用完,当前连接池没有空闲连接,连接池会根据acquireIncrement 该参数从新熊数据源获取一定数量的连接,但是连接池能获取的连接的最大数量,不能超过maxPoolSize设置的值,当连接池的连接为maxPoolSize值,且连接池没有可用空闲连接,客户端的请求只能在队列中等待,如果等待的时间超过checkoutTimeout 配置时间,则当前请求会抛SQLexception异常。 应用端getConnection抛出exception时, C3P0会测试其connection的有效性,并根据状态处理此connection,但应用端不会重调
6: 无论是网络问题还是远端数据库服务器,就算恢复正常后,客户端pool内其已存在的connection都会失效,要保证应用端调用无误,必须在checkout到应用端之前刷新这些无效connection ,针对这种情况,可以设置 testConnectionOnCheckout (connection提交的时候都将校验其有效性)和 testConnectionOnCheckin (取得连接的同时将校验连接的有效性),但是这两参数对性能的开销是非常大的,不建议使用。 建议使用idleConnectionTestPeriod或automaticTestTable 等方法来提升连接测试的性能 ,这两参数对定时的校验连接池的连接是否可用,不可用连接会被清除。breakAfterAcquireFailure 参数需设置为false,保障恢复正常后能够重新连接数据源,并建立连接。
7:当连接池空闲连接太多,可以设置 maxIdleTime ( 最大空闲时间 ) 和 idleConnectionTestPeriod ( 检查所有连接池中的空闲连接 )两个参数来清理连接池的空闲连接,也可设置 maxIdleTimeExcessConnection 不为0,让连接池的连接保持在minPoolSizede 数量
8:Oracle数据库校验登录失败次数(FAILED_LOGIN_ATTEMPTS)为10次,并且是一个不断叠加的过程,在保证密码正确之前,无论中间间隔多长时间,登陆失败连续超过十次,用户会被锁定,所以建议在不更改数据库设置的前提下,设置acquireIncrement 的值不要超过10,且重复加载的次数acquireRetryAttempts 不宜过多,(acquireRetryAttempts * acquireIncrement )+ initialPoolSize <FAILED_LOGIN_ATTEMPTS,否则容易造成数据库用户锁定