1. 程式人生 > >Java中的資料庫連線池原理

Java中的資料庫連線池原理

連線池的基本工作原理

1、基本概念及原理

我們知道,對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配?釋放所造成的問題。資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連線,當需要建立資料庫連線時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。我們可以通過設定連線池最大連線數來防止系統無盡的與資料庫連線。更為重要的是我們可以通過連線池的管理機制監視資料庫的連線的數量?使用情況,為系統開發?測試及效能調整提供依據。

2、伺服器自帶的連線池

JDBC的API中沒有提供連線池的方法。一些大型的WEB應用伺服器如BEA的WebLogic和IBM的WebSphere等提供了連線池的機制,但是必須有其第三方的專用類方法支援連線池的用法。

連線池關鍵問題分析

1、併發問題

為了使連線管理服務具有最大的通用性,必須考慮多執行緒環境,即併發問題。這個問題相對比較好解決,因為Java語言自身提供了對併發管理的支援,使用synchronized關鍵字即可確保執行緒是同步的。使用方法為直接在類方法前面加上synchronized關鍵字,如:

public synchronized Connection getConnection()

2、多資料庫伺服器和多使用者

對於大型的企業級應用,常常需要同時連線不同的資料庫(如連線Oracle和Sybase)。如何連線不同的資料庫呢?我們採用的策略是:設計一個符合單例模式的連線池管理類,在連線池管理類的唯一例項被建立時讀取一個資原始檔,其中資原始檔中存放著多個數據庫的url地址()?使用者名稱()?密碼()等資訊。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根據資原始檔提供的資訊,建立多個連線池類的例項,每一個例項都是一個特定資料庫的連線池。連線池管理類例項為每個連線池例項取一個名字,通過不同的名字來管理不同的連線池。

對於同一個資料庫有多個使用者使用不同的名稱和密碼訪問的情況,也可以通過資原始檔處理,即在資原始檔中設定多個具有相同url地址,但具有不同使用者名稱和密碼的資料庫連線資訊。

3、事務處理

我們知道,事務具有原子性,此時要求對資料庫的操作符合“ALL-ALL-NOTHING”原則,即對於一組SQL語句要麼全做,要麼全不做。

在Java語言中,Connection類本身提供了對事務的支援,可以通過設定Connection的AutoCommit屬性為false,然後顯式的呼叫commit或rollback方法來實現。但要高效的進行Connection複用,就必須提供相應的事務支援機制。可採用每一個事務獨佔一個連線來實現,這種方法可以大大降低事務管理的複雜性。

4、連線池的分配與釋放

連線池的分配與釋放,對系統的效能有很大的影響。合理的分配與釋放,可以提高連線的複用度,從而降低建立新連線的開銷,同時還可以加快使用者的訪問速度。

對於連線的管理可使用空閒池。即把已經建立但尚未分配出去的連線按建立時間存放到一個空閒池中。每當使用者請求一個連線時,系統首先檢查空閒池內有沒有空閒連線。如果有就把建立時間最長(通過容器的順序存放實現)的那個連線分配給他(實際是先做連線是否有效的判斷,如果可用就分配給使用者,如不可用就把這個連線從空閒池刪掉,重新檢測空閒池是否還有連線);如果沒有則檢查當前所開連線池是否達到連線池所允許的最大連線數(maxConn),如果沒有達到,就新建一個連線,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間內有連線被釋放出來就可以把這個連線分配給等待的使用者,如果等待時間超過預定時間timeout,則返回空值(null)。系統對已經分配出去正在使用的連線只做計數,當使用完後再返還給空閒池。對於空閒連線的狀態,可開闢專門的執行緒定時檢測,這樣會花費一定的系統開銷,但可以保證較快的響應速度。也可採取不開闢專門執行緒,只是在分配前檢測的方法。

5、連線池的配置與維護

連線池中到底應該放置多少連線,才能使系統的效能最佳?系統可採取設定最小連線數(minConn)和最大連線數(maxConn)來控制連線池中的連線。最小連線數是系統啟動時連線池所建立的連線數。如果建立過多,則系統啟動就慢,但建立後系統的響應速度會很快;如果建立過少,則系統啟動的很快,響應起來卻慢。這樣,可以在開發時,設定較小的最小連線數,開發起來會快,而在系統實際使用時設定較大的,因為這樣對訪問客戶來說速度會快些。最大連線數是連線池中允許連線的最大數目,具體設定多少,要看系統的訪問量,可通過反覆測試,找到最佳點。

如何確保連線池中的最小連線數呢?有動態和靜態兩種策略。動態即每隔一定時間就對連線池進行檢測,如果發現連線數量小於最小連線數,則補充相應數量的新連線,以保證連線池的正常運轉。靜態是發現空閒連線不夠時再去檢查。

連線池的實現

1、連線池模型

本文討論的連線池包括一個連線池類(DBConnectionPool)和一個連線池管理類(DBConnetionPoolManager)。連線池類是對某一資料庫所有連線的“緩衝池”,主要實現以下功能:①從連線池獲取或建立可用連線;②使用完畢之後,把連線返還給連線池;③在系統關閉前,斷開所有連線並釋放連線佔用的系統資源;④還能夠處理無效連線(原來登記為可用的連線,由於某種原因不再可用,如超時,通訊問題),並能夠限制連線池中的連線總數不低於某個預定值和不超過某個預定值。

連線池管理類是連線池類的外覆類(wrapper),符合單例模式,即系統中只能有一個連線池管理類的例項。其主要用於對多個連線池物件的管理,具有以下功能:①裝載並註冊特定資料庫的JDBC驅動程式;②根據屬性檔案給定的資訊,建立連線池物件;③為方便管理多個連線池物件,為每一個連線池物件取一個名字,實現連線池名字與其例項之間的對映;④跟蹤客戶使用連線情況,以便需要是關閉連線釋放資源。連線池管理類的引入主要是為了方便對多個連線池的使用和管理,如系統需要連線不同的資料庫,或連線相同的資料庫但由於安全性問題,需要不同的使用者使用不同的名稱和密碼。

2、連線池實現

下面給出連線池類和連線池管理類的主要屬性及所要實現的基本介面:

public class DBConnectionPool implements TimerListener{  
private int checkedOut;//已被分配出去的連線數  
private ArrayList freeConnections=new ArrayList();
//容器,空閒池,根據//建立時間順序存放已建立但尚未分配出去的連線  
private    int    minConn;//連線池裡連線的最小數量  
private    int    maxConn;//連線池裡允許存在的最大連線數  
private    String    name;//為這個連線池取個名字,方便管理  
private    String    password;//連線資料庫時需要的密碼  
private    String    url;//所要建立連線的資料庫的地址  
private    String    user;//連線資料庫時需要的使用者名稱  
public    Timer    timer;//定時器  
public    DBConnectionPool(String name,String URL,String user,
String password,int maxConn)//公開的建構函式  
public synchronized void freeConnection(Connection con)  
//使用完畢之後,把連線返還給空閒池  
public synchronized Connection getConnection(long    timeout)
//得到一個連線,timeout是等待時間  
public synchronized void release()
//斷開所有連線,釋放佔用的系統資源  
private Connection newConnection()
//新建一個數據庫連線  
public synchronized void TimerEvent()    
//定時器事件處理函式  
}  
public class DBConnectionManager {  
static private DBConnectionManager instance;
//連線池管理類的唯一例項  
static private int clients;//客戶數量  
private ArrayList drivers=new ArrayList();
//容器,存放資料庫驅動程式  
private HashMap pools = new HashMap();
//以name/value的形式存取連線池物件的名字及連線池物件  
static synchronized public DBConnectionManager getInstance()
/**如果唯一的例項instance已經建立,直接返回這個例項;否則,呼叫私有建構函式,
建立連線池管理類的唯一例項*/      
private DBConnectionManager()
//私有建構函式,在其中呼叫初始化函式init()  
public void freeConnection(String name,Connection con)
//釋放一個連線,name是一個連線池物件的名字  
public Connection getConnection(String name)
//從名字為name的連線池物件中得到一個連線  
public Connection getConnection(String name,long time)
//從名字為name的連線池物件中取得一個連線,time是等待時間  
public synchronized void release()//釋放所有資源  
private void createPools(Properties props)
//根據屬性檔案提供的資訊,建立一個或多個連線池  
private void init()//初始化連線池管理類的唯一例項,由私有建構函式呼叫  
private void loadDrivers(Properties props)//裝載資料庫驅動程式  
}

3、連線池使用

上面所實現的連線池在程式開發時如何應用到系統中呢?下面以Servlet為例說明連線池的使用。

Servlet的生命週期是:在開始建立servlet時,呼叫其初始化(init)方法。之後每個使用者請求都導致一個呼叫前面建立的例項的service方法的執行緒。最後,當伺服器決定解除安裝一個servlet時,它首先呼叫該servlet的destroy方法。

根據servlet的特點,我們可以在初始化函式中生成連線池管理類的唯一例項(其中包括建立一個或多個連線池)。如:

public void init() throws ServletException  
{  
 connMgr=DBConnectionManager.getInstance();      
}

然後就可以在service方法中通過連線池名稱使用連線池,執行資料庫操作。最後在destroy方法中釋放佔用的系統資源,如:

public void destroy(){      
connMgr.release();    
super.destroy();      
}

=========================================

Spring中配置資料庫連線池

1.建立一個properties檔案

#MYSQL
#driverClassName=com.mysql.jdbc.Driver
#url=jdbc:mysql://127.0.0.1:3306/school?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
#username=root
#password=

#Oracle
#driverClassName=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@192.168.1.85:1521:mys
#username=mawmtest
#password=1

driverClassName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@192.168.1.142:1521:ora9i
username=jax_yy_admin
password=yy_admin

#driverClassName=com.mysql.jdbc.Driver
#url=jdbc:mysql://127.0.0.1:3306/yesidatfwq1?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
#username=root
#password=root

#driverClassName=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@127.0.0.1:1521:yes
#username=yesido
#password=yesido

initialSize=10
maxActive=50
maxIdle=20
minIdle=5
maxWait=60000

##connectionProperties=useUnicode=true;characterEncoding=utf8
#defaultTransactionIsolation=READ_UNCOMMITTED


2.spring的xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
			">
	<!--=========================↓↓↓=====配置檔案方式連線資料庫======↓↓↓=======================-->



	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jaxdb.properties</value>
			</list>
		</property>
	</bean>

	 
	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName">
			<value>${driverClassName}</value>
		</property>
		<property name="url">
			<value>${url}</value>
		</property>
		<property name="username">
			<value>${username}</value>
		</property>
		<property name="password">
			<value>${password}</value>
		</property>

		<property name="initialSize">
			<value>${initialSize}</value>
		</property>
		<property name="maxActive">
			<value>${maxActive}</value>
		</property>
		<property name="maxIdle">
			<value>${maxIdle}</value>
		</property>
		<property name="maxWait">
			<value>${maxWait}</value>
		</property>



	</bean>
	<!--=========================↑↑↑=====配置檔案方式連線資料庫======↑↑↑======================-->

	<!--=========================↓↓↓=====JNDI方式連線資料庫======↓↓↓=======================-->

	<!-- copy下面這句到 web.xml中,修改 jndiName的名字和實際配置的一致
		
		<resource-ref >
		<res-ref-name>jdbc/jaxkaoshi</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
		<res-sharing-scope>Shareable</res-sharing-scope>
		</resource-ref>		
		
		
	-->
	<!-- 
		<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">	
		<property name="jndiName"><value>jdbc/jaxkaoshi</value></property> 
		<property name="resourceRef"><value>true</value></property> 		
		</bean>
	-->

	<!--=========================↑↑↑=====JNDI方式連線資料庫======↑↑↑======================-->


</beans>



=========================================

結束語

在使用JDBC進行與資料庫有關的應用開發中,資料庫連線的管理是一個難點。很多時候,連線的混亂管理所造成的系統資源開銷過大成為制約大型企業級應用效率的瓶頸。對於眾多使用者訪問的Web應用,採用資料庫連線技術的系統在效率和穩定性上比採用傳統的其他方式的系統要好很多。本文闡述了使用JDBC訪問資料庫的技術?討論了基於連線池技術的資料庫連線管理的關鍵問題並給出了一個實現模型。文章所給出的是連線池管理程式的一種基本模式,為提高系統的整體效能,在此基礎上還可以進行很多有意義的擴充套件。


相關推薦

Java資料庫連線原理機制的詳細講解

連線池的基本工作原理   1、基本概念及原理   由上面的分析可以看出,問題的根源就在於對資料庫連線資源的低效管理。我們知道,對於共享資源,有一個很著名的設計模式:資源池 (Resource Pool)。該模式正是為了解決資源的頻繁分配?釋放所造成的問題。為解決上述問

JAVA和C#資料庫連線原理與應用

JAVA和C#中資料庫連線池原理 在現在的網際網路發展中,高併發成為了主流,而最關鍵的部分就是對資料庫操作和訪問,在現在的網際網路發展中,ORM框架曾出不窮, 比如:.Net-Core的EFCore、SqlSugar、Dapper。JAVA的Spring-DataJpa(EntityManager),Myba

Java資料庫連線原理

連線池的基本工作原理 1、基本概念及原理 我們知道,對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配?釋放所造成的問題。資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連

Java資料庫連線原理與簡易實現

1、什麼是資料庫連線池     我們現在在開發中一定都會用到資料庫,為了提高我們的系統的訪問速度,資料庫優化是一個有效的途徑。我們現在開發中使用資料庫一般都要經歷以下的四個步驟:(1)載入資料庫的驅動類,(2)建立資料庫連線,(3)進行資料操作,(4)關閉資料庫連線;在這四步中建立資料庫連線是一個比較耗時的操

Java配置資料庫連線

dbcp資料庫連線池 DbcpUtils.java import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; impor

資料庫連線原理及應用

1、運作原理 在實際應用開發中,特別是在WEB應用系統中,如果JSP、Servlet或EJB使用 JDBC直接訪問資料庫中的資料,每一次資料訪問請求都必須經歷建立資料庫連線、開啟資料庫、存取資料和關閉資料庫連線等步驟,而連線並開啟資料庫是一件既消耗資源又費時的工作,如果頻繁發生這種資料庫操作,系

物件資料庫連線原理

一、一點說明: (本文的知識點來自C#執行緒參考手冊) 物件池在企業軟體中非常常見,為了提供應用的效能,必須控制物件例項的建立。比如建立資料庫連線物件,每一次建立的代價非常高昂,每一次使用資料庫都需要連線資料庫,代價非常高昂,因此有了資料庫連線池,每一次一個連線被建立之後不是就馬上釋放,下一次使用的時候重

Java框架資料庫連線

Java框架資料庫連線池比較(c3p0,dbcp和proxool)  現在常用的開源資料連線池主要有c3p0,dbcp和proxool三種,其中: ¨         hiber

java配置資料庫連線的方法步驟

先來了解下什麼是資料庫連線池 資料庫連線池技術的思想非常簡單,將資料庫連線作為物件儲存在一個Vector物件中,一旦資料庫連線建立後,不同的資料庫訪問請求就可以共享這些連線,這樣,通過複用這些已經建立的資料庫連線,可以克服上述缺點,極大地節省系統資源和時間。 在實際應用開

java建立資料庫連線程式碼

       資料庫連線池(Connection pooling)是程式啟動時建立足夠的資料庫連線,並將這些連線組成一個連線池,由程式動態地對池中的連線進行申請,使用,釋放。        大家可以想一下,如果專案中沒有資料庫連線池會是一個什麼樣的結果?每訪問一次資料庫

Java jdbc資料庫連線總結!

1. 引言   近年來,隨著Internet/Intranet建網技術的飛速發展和在世界範圍內的迅速普及,計算機   應用程式已從傳統的桌面應用轉到Web應用。基於B/S(Browser/Server)架構的3層開發模式逐漸取代C/S(Client/Server)架構的開發

j2ee資料庫連線原理分析

最近我作了JSP資料庫的頻繁連線,在此給出資料庫連線池的必要性,對於JSP來說一個很好的J2EE伺服器是很必要的,JBOOS,WebLogic都是很好的解決方案。 一般情況下,在使用開發基於資料庫的WEB程式時,傳統的模式基本是按以下步驟: 1. 在主程式(如Serv

Java框架資料庫連線比較(c3p0,dbcp和proxool)

現在常用的開源資料連線池主要有c3p0,dbcp和proxool三種,其中:  ¨         hibernate開發組推薦使用c3p0;  ¨         spring開發組推薦使用dbcp (dbcp連線池有weblogic連線池同樣的問題,就是強行關閉連

淺析資料庫連線原理分析與實現

1 動機在專案初期對於資料庫的使用就是開啟一個連線並進行使用,使用過後關閉連線釋放資源,並且在後臺簡單測試中,並沒有出現問題。但是在與前端對接之後,發現頻繁地開啟和關閉連線會對效能造成很大的影響,而且之前假設的情況是接受的請求都是同步的,但是前端可能傳送非同步請求,當兩個請求

Spring資料庫連線需要注意的問題

<property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/seckill?

資料庫連線原理詳解與自定義連線實現

實現原理資料庫連線池在初始化時將建立一定數量的資料庫連線放到連線池中,這些資料庫連線的數量是由最小資料庫連線數制約。無論這些資料庫連線是否被使用,連線池都將一直保證至少擁有這麼多的連線數量。連線池的最大資料庫連線數量限定了這個連線池能佔有的最大連線數,當應用程式向連線池請求的連

【最近面試遇到的一些問題】資料庫連線的優點和原理,常用的java開源連線元件

資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得尤為突出。對資料庫連線的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連線池正是針對這個問題提出來的。資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用

mysql筆記五——資料庫連線原理、構建)和java動態代理的使用

資料庫連線池 1、什麼是資料庫連線池?       資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是再重新建立一個;釋放空閒時間超過最大空閒時間的資料庫連線來避免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。這項

JavaJDBC的資料庫連線

資料庫連線池 池引數(所有池引數都有預設值): 初始大小:10個 最小空閒連線數:3個 增量:一次建立的最小單位(5個) 最大空閒連線數:12個 最大連線數:20個 最大的等待時間:1000毫秒 四

使用JAVA的動態代理實現資料庫連線

資料庫連線池在編寫應用服務是經常需要用到的模組,太過頻繁的連線資料庫對服務效能來講是一個瓶頸,使用緩衝池技術可以來消除這個瓶頸。我們可以在網際網路上找到很多關於資料庫連線池的源程式,但是都發現這樣一個共同的問題:這些連線池的實現方法都不同程度地增加了與使用者之間的耦合度。很多