数据库连接池的选择及其开发配置
轉載自? 數據庫連接池的選擇及其開發配置
一、數據庫連接池概述
數據庫連接的建立是一種耗時、性能低、代價高的操作,頻繁的數據庫連接的建立和關閉極大的影響了系統的性能。數據庫連接池是系統初始化過程中創建一定數量的數據庫連接放于連接池中,當程序需要訪問數據庫時,不再建立一個新的連接,而是從連接池中取出一個已建立的空閑連接,使用完畢后,程序將連接歸還到連接池中,供其他請求使用,從而實現的資源的共享,連接的建立、斷開都由連接池自身來管理。
數據庫連接池為系統的運行帶來了以下優勢:昂貴的數據庫連接資源得到重用;減少了數據庫連接建立和釋放的時間開銷,提高了系統響應速度;統一的數據庫連接管理,避免了連接資源的泄露。
數據庫連接池運行機制:系統初始化時創建連接池,程序操作數據庫時從連接池中獲取空閑連接,程序使用完畢將連接歸還到連接池中,系統退出時,斷開所有數據庫連接并釋放內存資源。
二、主流數據庫連接池比較
常用的主流開源數據庫連接池有C3P0、DBCP、Tomcat Jdbc Pool、BoneCP、Druid等
1、C3p0:?開源的JDBC連接池,實現了數據源和JNDI綁定,支持JDBC3規范和JDBC2的標準擴展。目前使用它的開源項目有Hibernate、Spring等。單線程,性能較差,適用于小型系統,代碼600KB左右。
2、DBCPDBCP (Database Connection Pool):由Apache開發的一個Java數據庫連接池項目, Jakarta commons-pool對象池機制,Tomcat使用的連接池組件就是DBCP。單獨使用dbcp需要3個包:common-dbcp.jar,common-pool.jar,common-collections.jar,預先將數據庫連接放在內存中,應用程序需要建立數據庫連接時直接到連接池中申請一個就行,用完再放回。單線程,并發量低,性能不好,適用于小型系統。
3、Tomcat Jdbc Pool:Tomcat在7.0以前都是使用common-dbcp做為連接池組件,但是dbcp是單線程,為保證線程安全會鎖整個連接池,性能較差,dbcp有超過60個類,也相對復雜。Tomcat從7.0開始引入了新增連接池模塊叫做Tomcat jdbc pool,基于Tomcat JULI,使用Tomcat日志框架,完全兼容dbcp,通過異步方式獲取連接,支持高并發應用環境,超級簡單核心文件只有8個,支持JMX,支持XA Connection。
4、BoneCP:官方說法BoneCP是一個高效、免費、開源的Java數據庫連接池實現庫。設計初衷就是為了提高數據庫連接池性能,根據某些測試數據顯示,BoneCP的速度是最快的,要比當時第二快速的連接池快25倍左右,完美集成到一些持久化產品如Hibernate和DataNucleus中。BoneCP特色:高度可擴展,快速;連接狀態切換的回調機制;允許直接訪問連接;自動化重置能力;JMX支持;懶加載能力;支持XML和屬性文件配置方式;較好的Java代碼組織,100%單元測試分支代碼覆蓋率;代碼40KB左右。
5、Druid:Druid是Java語言中最好的數據庫連接池,Druid能夠提供強大的監控和擴展功能,是一個可用于大數據實時查詢和分析的高容錯、高性能的開源分布式系統,尤其是當發生代碼部署、機器故障以及其他產品系統遇到宕機等情況時,Druid仍能夠保持100%正常運行。主要特色:為分析監控設計;快速的交互式查詢;高可用;可擴展;Druid是一個開源項目,源碼托管在github上。
主流連接池各項功能對比如下:
三、連接池Spring集成配置與JNDI配置
下面針對每一種連接池的使用方法,在開發中如何配置給出spring集成配置和在tomcat的conf/context.xml文件中配置2種方式,限于篇幅只給出基本參數,詳細參數可自行研究。
3.1 阿里Druid連接池Maven依賴
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.28</version> </dependency>Spring集成配置方式
<!--Spring?Druid?數據源配置--> <bean?id="dataSource"?class="com.alibaba.druid.pool.DruidDataSource"?init-method="init"?destroy-method="close"> <!--?基本屬性?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="1"?/> <property?name="minIdle"?value="1"?/> <property?name="maxActive"?value="20"?/> <!--?配置獲取連接等待超時的時間?--> <property?name="maxWait"?value="60000"?/> <!--?配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒?--> <property?name="timeBetweenEvictionRunsMillis"?value="60000"?/> <!--?配置一個連接在池中最小生存的時間,單位是毫秒?--> <property?name="minEvictableIdleTimeMillis"?value="300000"?/> <!--?打開PSCache,并且指定每個連接上PSCache的大小?--> <property?name="poolPreparedStatements"?value="true"?/> <property?name="maxPoolPreparedStatementPerConnectionSize"?value="20"?/> <!--?配置監控統計攔截的filters,去掉后監控界面sql無法統計?--> <property?name="filters"?value="stat"?/> </bean>Web.xml配置<!--druid?WebStatFilter用于采集web-jdbc關聯監控的數據--><filter><filter-name>DruidWebStatFilter</filter-name><filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class><init-param><param-name>exclusions</param-name><param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value></init-param></filter><filter-mapping><filter-name>DruidWebStatFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--druid訪問監控界面?/druid/index.html--><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>Tomcat中context.xml文件JNDI配置方式
com.alibaba.druid.pool.DruidDataSourceFactory實現了javax.naming.spi.ObjectFactory,可以作為JNDI數據源來配置/conf/context.xml配置JNDI方式
?<Resourcename="jdbc/MysqlDataSource"factory="com.alibaba.druid.pool.DruidDataSourceFactory"auth="Container"type="javax.sql.DataSource"driverClassName="com.mysql.jdbc.Driver"url="jdbc:mysql://192.168.1.233:3306/lead_oams?useUnicode=true&characterEncoding=utf-8"username="lead_system"password="password"maxActive="50"maxWait="10000"removeabandoned="true"removeabandonedtimeout="60"logabandoned="false"filters="stat"/>web.xml配置
?<!--MySQL數據庫JNDI數據?--><resource-ref><description>MySQL?DB?Connection</description><res-ref-name>jdbc/MysqlDataSource</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth></resource-ref>Java代碼中獲取JNDI數據源
//1、初始化名稱查找上下文
?Context?ctx?=new?InitialContext();//2、通過JNDI名稱找到DataSource
?DruidDataSource?ds?=?(DruidDataSource)ctx.lookup("java:comp/env/jdbc/MysqlDataSource");//3、通過ds獲取數據庫連接對象
??Connectionconn?=?ds.getConnection();3.2 BoneCP連接池Maven依賴
<dependency><groupId>com.jolbox</groupId><artifactId>bonecp-spring</artifactId><version>0.8.0.RELEASE</version> </dependency>Spring集成BoneCP配置方式
<!--?Spring?BoneCP?數據源配置--><bean?id="dataSource"?class="com.jolbox.bonecp.BoneCPDataSource"?destroy-method="close"><!--?數據庫驅動?--><property?name="driverClass"?value="${jdbc.driver}"?/><!--?相應驅動的jdbcUrl?--><property?name="jdbcUrl"?value="${jdbc.url}"?/><!--?數據庫的用戶名?--><property?name="username"?value="${jdbc.username}"?/><!--?數據庫的密碼?--><property?name="password"?value="${jdbc.password}"?/><!--?檢查數據庫連接池中空閑連接的間隔時間,單位是分,默認值:240,如果要取消則設置為0?--><property?name="idleConnectionTestPeriod"?value="60"?/><!--?連接池中未使用的鏈接最大存活時間,單位是分,默認值:60,如果要永遠存活設置為0?--><property?name="idleMaxAge"?value="30"?/><!--?每個分區最大的連接數?--><property?name="maxConnectionsPerPartition"?value="150"?/><!--?每個分區最小的連接數?--><property?name="minConnectionsPerPartition"?value="5"?/></bean>Tomcat中BoneCP使用JNDI配置方式
<Resourcename="JNDIName"auth="Container"type="com.jolbox.bonecp.BoneCPDataSource"factory="org.apache.naming.factory.BeanFactory"driverClass="oracle.jdbc.driver.OracleDriver"username="root"? password="root"?jdbcUrl="jdbc:mysql://localhost:3306/test"idleConnectionTestPeriod="0"idleMaxAge="10"partitionCount="1"maxConnectionsPerPartition="5"minConnectionsPerPartition="1"connectionTestStatement=""initSQL="select?1?from?dual"/>Java代碼中獲取JNDI數據源
//1、初始化名稱查找上下文
??Context?ctx?=new?InitialContext();//2、通過JNDI名稱找到DataSource
?DataSource?ds=?(DataSource)?ctx.lookup("java:comp/env/jdbc/MysqlDataSource");//3、通過ds獲取數據庫連接對象
Connectionconn?=?ds.getConnection();3.3 Tomcat Jdbc Pool連接池Maven依賴
<dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-jdbc</artifactId><version>7.0.75</version> </dependency> <dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-juli</artifactId><version>7.0.75</version> </dependency>Spring集成Tomcat Jbdc Pool配置方式
<!--tomcat?jdbc?pool數據源配置-->?<bean?id="dataSource"?class="org.apache.tomcat.jdbc.pool.DataSource"?destroy-method="close"><property?name="poolProperties"><bean?class="org.apache.tomcat.jdbc.pool.PoolProperties"><!--driverClassName?url?username?password--><property?name="driverClassName"?value="com.mysql.jdbc.Driver"/><property?name="url"?value="jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"/><property?name="username"?value="root"/><property?name="password"?value="root"/><!--jmx?support--><property?name="jmxEnabled"?value="true"/><property?name="testWhileIdle"?value="true"/><property?name="testOnBorrow"?value="true"/><property?name="testOnReturn"?value="false"/><property?name="validationInterval"?value="30000"/><property?name="validationQuery"?value="SELECT?1"/><property?name="timeBetweenEvictionRunsMillis"?value="30000"/><!--最大連接--><property?name="maxActive"?value="50"/><!--初始化連接--><property?name="initialSize"?value="5"/><!--最長等待時間ms--><property?name="maxWait"?value="10000"/><property?name="minEvictableIdleTimeMillis"?value="30000"/><property?name="minIdle"?value="10"/><!--是否允許日志--><property?name="logAbandoned"?value="false"/><property?name="removeAbandoned"?value="true"/><property?name="removeAbandonedTimeout"?value="60"/><property?name="jdbcInterceptors"?value="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"/></bean>Tomcat中context.xml文件JNDI配置方式
<Resource??? name="jdbc/test"?? auth="Container"?? factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"?? testWhileIdle="true"?? testOnBorrow="true"?? testOnReturn="false"?? validationQuery="SELECT?1"?? validationInterval="30000"?? timeBetweenEvictionRunsMillis="30000"?? driverClassName="com.mysql.jdbc.Driver"?? maxActive="100"?? maxIdle="40" maxWait="12000"?? initialSize="10"?? removeAbandonedTimeout="60"?? removeAbandoned="true"?? logAbandoned="true"?? minEvictableIdleTimeMillis="30000"?? jmxEnabled="true"?? jdbcInterceptors=??"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"?? username="root"? password="root"? type="javax.sql.DataSource"??? url="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"/>Java代碼中獲取JNDI數據源
//1、初始化名稱查找上下文
?Context?ctx?=new?InitialContext();//2、通過JNDI名稱找到DataSource
DataSource?ds=?(DataSource)?ctx.lookup("java:comp/env/jdbc/test");//3、通過ds獲取數據庫連接對象
Connectionconn?=?ds.getConnection();3.4 Apache DBCP連接池Maven依賴
<dependency><groupId>commons-dbcp</groupId><artifactId>commons-dbcp</artifactId><version>1.4</version> </dependency> <dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2.2</version> </dependency> <dependency><groupId>commons-pool</groupId><artifactId>commons-pool</artifactId><version>1.6</version> </dependency>Spring集成DBCP配置方式
?<!--?配置dbcp數據源?--><bean?id="dataSource"?destroy-method="close"?class="org.apache.commons.dbcp.BasicDataSource"> <property?name="driverClassName"?value="${jdbc.driverClassName}"/> <property?name="url"?value="${jdbc.url}"/> <property?name="username"?value="${jdbc.username}"/> <property?name="password"?value="${jdbc.password}"/> <!--?池啟動時創建的連接數量?--> <property?name="initialSize"?value="5"/> <!--?同一時間可以從池分配的最多連接數量。設置為0時表示無限制。?--> <property?name="maxActive"?value="50"/> <!--?池里不會被釋放的最多空閑連接數量。設置為0時表示無限制。?--> <property?name="maxIdle"?value="10"/> <!--?在不新建連接的條件下,池中保持空閑的最少連接數。?--> <property?name="minIdle"?value="3"/> <!--?設置自動回收超時連接?-->?? <property?name="removeAbandoned"?value="true"?/> <!--?自動回收超時時間(以秒數為單位)?-->?? <property?name="removeAbandonedTimeout"?value="200"/> <!--?設置在自動回收超時連接的時候打印連接的超時錯誤??-->? <property?name="logAbandoned"?value="true"/> <!--?等待超時以毫秒為單位,在拋出異常之前,池等待連接被回收的最長時間(當沒有可用連接時)。設置為-1表示無限等待。-->?? <property?name="maxWait"?value="100"/>??</bean>Tomcat中context.xml文件JNDI配置方式
<Resource?name="/jdbc/test"?type="javax.sql.DataSource"?driverClassName="com.sybase.jdbc3.jdbc.SybDataSource"?url="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"?username="root"?password="root"?initialSize="5"maxActive="50"?maxIdle="10"?minIdle="3"maxWait="50000"?/>Java代碼中獲取JNDI數據源
//1、初始化名稱查找上下文
Context?ctx?=new?InitialContext();//2、通過JNDI名稱找到DataSource
DataSource?ds=?(DataSource)?ctx.lookup("java:comp/env/jdbc/test");//3、通過ds獲取數據庫連接對象
Connectionconn?=?ds.getConnection();3.5 C3p0連接池Maven依賴
<dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version> </dependency>Spring集成配置方式
<!--?Spring配置c3p0數據源?--> <bean?id="dataSource"?class="com.mchange.v2.c3p0.ComboPooledDataSource"?destroy-method="close"> <property?name="jdbcUrl"?value="${jdbc.url}"?/> <property?name="driverClass"?value="${jdbc.driverClassName}"?/> <property?name="user"?value="${jdbc.username}"?/> <property?name="password"?value="${jdbc.password}"?/> <!--連接池中保留的最大連接數。Default:?15?--> <property?name="maxPoolSize"?value="100"?/> <!--連接池中保留的最小連接數。--> <property?name="minPoolSize"?value="1"?/> <!--初始化時獲取的連接數,取值應在minPoolSize與maxPoolSize之間。Default:?3?--> <property?name="initialPoolSize"?value="10"?/> <!--最大空閑時間,60秒內未使用則連接被丟棄。若為0則永不丟棄。Default:?0?--> <property?name="maxIdleTime"?value="30"?/> <!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default:?3?--> <property?name="acquireIncrement"?value="5"?/> <!--JDBC的標準參數,用以控制數據源內加載的PreparedStatements數量。Default:?0--> <property?name="maxStatements"?value="0"?/> <!--每60秒檢查所有連接池中的空閑連接。Default:?0?--> <property?name="idleConnectionTestPeriod"?value="60"?/> <!--定義在從數據庫獲取新連接失敗后重復嘗試的次數。Default:?30?--> <property?name="acquireRetryAttempts"?value="30"?/> <!--獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。Default:?false--> <property?name="breakAfterAcquireFailure"?value="true"?/> <!--因性能消耗大請只在需要的時候使用它。Default:?false?--> <property?name="testConnectionOnCheckout"??value="false"?/> </bean>Tomcat中context.xml文件JNDI配置方式
<Resource?name="jdbc/MysqlDataSource"?auth="Container"factory="org.apache.naming.factory.BeanFactory"?type="com.mchange.v2.c3p0.ComboPooledDataSource"driverClass="com.mysql.jdbc.Driver"idleConnectionTestPeriod="60"maxPoolSize="50"?minPoolSize="2"acquireIncrement="2"?user="root"?password="root"jdbcUrl="jdbc:mysql://localhost:3306/test"/>Java代碼中獲取JNDI數據源
//1、初始化名稱查找上下文
Context?ctx?=new?InitialContext();//2、通過JNDI名稱找到DataSource
DataSource?ds=?(DataSource)?ctx.lookup("java:comp/env/jdbc/MysqlDataSource");//3、通過ds獲取數據庫連接對象
Connectionconn?=?ds.getConnection(); 總結本文所比較的5種數據庫連接池在性能方面,根據個人測試結果和參考網上資料Druid > TomcatJDBC > DBCP > C3P0,BoneCP的性能方面沒有深入比較,應該和Tomcat Jdbc差不多。
對于小型的系統,并發壓力不大時,選擇哪一種數據庫連接池差別不會很大,主要考慮的應該是連接池的穩定性。當并發量較高時,一般不會選擇使用DBCP和C3P0,選擇Druid是較好的。
本文給出了5種數據庫連接池通過Spring配置和Tomcat JNDI方式配置兩種方式,Spring配置一般使用單獨的屬性文件,每一個連接池都提供了使用代碼創建的方式,使用方式也比較類似,感興趣可以自行研究。
另外連接不同的數據庫時,在配置方面的差異主要在driverClass和jdbcUrl兩項,優化配置項可以另行考慮。
總結
以上是生活随笔為你收集整理的数据库连接池的选择及其开发配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计电脑配置推荐2022(设计 电脑配置
- 下一篇: 彻底理解数据库事务