對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是爲了解決資源的頻繁分配﹑釋放所形成的問題。數據庫鏈接池的基本思想就是爲數據庫鏈接創建一個「緩衝池」。預先在緩衝池中放入必定數量的鏈接,當須要創建數據庫鏈接時,只需從「緩衝池」中取出一個,使用完畢以後再放回去。咱們能夠經過設定鏈接池最大鏈接數來防止系統無盡的與數據庫鏈接。更爲重要的是咱們能夠經過鏈接池的管理機制監視數據庫的鏈接的數量﹑使用狀況,爲系統開發﹑測試及性能調整提供依據。html
鏈接,是咱們的編程語言與數據庫交互的一種方式。咱們常常會聽到這麼一句話「數據庫鏈接很昂貴「。java
有人接受這種說法,殊不知道它的真正含義。所以,下面經過實例解釋它到底是什麼。mysql
下面是MySQL數據庫建立鏈接的的一段代碼:web
[java] view plain copy print?spring
當咱們建立了一個Connection對象,它在內部都執行了什麼:sql
1.「DriverManager」檢查並註冊驅動程序;數據庫
2.「com.mysql.jdbc.Driver」就是咱們註冊了的驅動程序,它會在驅動程序類中調用「connect(url…)」方法。apache
3.com.mysql.jdbc.Driver的connect方法根據咱們請求的「connUrl」,建立一個「Socket鏈接」,鏈接到IP爲「your.database.domain」,默認端口3306的數據庫。編程
4.建立的Socket鏈接將被用來查詢咱們指定的數據庫,並最終讓程序返回獲得一個結果。c#
簡單的獲取一個鏈接,系統卻要在背後作不少消耗資源的事情,大多時候,建立鏈接的時間比執行sql語句的時間還要長。
傳統的獲取鏈接方式以下圖所示:
用戶每次請求都須要向數據庫得到連接,而數據庫建立鏈接一般須要消耗相對較大的資源,建立時間也較長。假設網站一天10萬訪問量,數據庫服務器就須要建立10萬次鏈接,極大的浪費數據庫的資源,而且極易形成數據庫服務器內存溢出、拓機。
採用鏈接池技術後的過程以下:
數據庫鏈接是一種關鍵的有限的昂貴的資源,這一點在多用戶的網頁應用程序中體現的尤其突出。對數據庫鏈接的管理能顯著影響到整個應用程序的伸縮性和健壯性,影響到程序的性能指標。數據庫鏈接池負責分配,管理和釋放數據庫鏈接,它容許應用程序重複使用一個現有的數據庫鏈接,而不是從新創建一個。
一、併發問題
爲了使鏈接管理服務具備最大的通用性,必須考慮多線程環境,即併發問題。這個問題相對比較好解決,由於各個語言自身提供了對併發管理的支持像Java,c#等等,使用synchronized(java)、lock(C#)關鍵字便可確保線程是同步的。
二、事務處理
咱們知道,事務具備原子性,此時要求對數據庫的操做符合「ALL-OR-NOTHING」原則,即對於一組SQL語句要麼全作,要麼全不作。
咱們知道當2個線程公用一個鏈接Connection對象,並且各自都有本身的事務要處理時候,對於鏈接池是一個很頭疼的問題,由於即便Connection類提供了相應的事務支持,但是咱們仍然不能肯定那個數據庫操做是對應那個事務的,這是因爲咱們有2個線程都在進行事務操做而引發的。爲此咱們可使用每個事務獨佔一個鏈接來實現,雖然這種方法有點浪費鏈接池資源可是能夠大大下降事務管理的複雜性。
3、鏈接池的分配與釋放
鏈接池的分配與釋放,對系統的性能有很大的影響。合理的分配與釋放,能夠提升鏈接的複用度,從而下降創建新鏈接的開銷,同時還能夠加快用戶的訪問速度。
對於鏈接的管理可以使用一個List。即把已經建立的鏈接都放入List中去統一管理。每當用戶請求一個鏈接時,系統檢查這個List中有沒有能夠分配的鏈接。若是有就把那個最合適的鏈接分配給他(如何能找到最合適的鏈接文章將在關鍵議題中指出);若是沒有就拋出一個異常給用戶,List中鏈接是否能夠被分配由一個線程來專門管理。
4、鏈接池的配置與維護
鏈接池中到底應該放置多少鏈接,才能使系統的性能最佳?系統可採起設置最小鏈接數(minConnection)和最大鏈接數(maxConnection)等參數來控制鏈接池中的鏈接。比方說,最小鏈接數是系統啓動時鏈接池所建立的鏈接數。若是建立過多,則系統啓動就慢,但建立後系統的響應速度會很快;若是建立過少,則系統啓動的很快,響應起來卻慢。這樣,能夠在開發時,設置較小的最小鏈接數,開發起來會快,而在系統實際使用時設置較大的,由於這樣對訪問客戶來講速度會快些。最大鏈接數是鏈接池中容許鏈接的最大數目,具體設置多少,要看系統的訪問量,可經過軟件需求上獲得。
如何確保鏈接池中的最小鏈接數呢?有動態和靜態兩種策略。動態即每隔必定時間就對鏈接池進行檢測,若是發現鏈接數量小於最小鏈接數,則補充相應數量的新鏈接,以保證鏈接池的正常運轉。靜態是發現空閒鏈接不夠時再去檢查。
Tomcat默認使用的是DBCP數據庫鏈接池,其實從本質上講,Tomcat是利用Apache Commons DBCP來實現的,只不過把特定的功能集成到了tomcat-dbcp.jar包中。
使用法法以下:
步驟1:
在Tomcat中Context.xml中添加
[html] view plain copy print?
注:還能夠用minIdle配置鏈接池中最少空閒maxIdle個鏈接,用initialSize配置初始化鏈接數目。可同時配置多個數據源。
若是在Tomcat的server.xml文件中配置數據源,有兩種方法均可以實現:
方法1:將上面的配置內容直接添加在<Host>節點下。
方法2:在<GlobalNamingResources>節點下添加:
[html] view plain copy print?
而後在context.xml文件中的<Context></Context>節點中加入以下內容:
[html] view plain copy print?
在server.xml中配置的數據源是全局的,全部項目均可以使用。全局的resource只是爲了重用,方便全部該tomcat下的web工程的數據源管理,但若是你的tomcat不會同時加載多個web工程,也就是說一個tomcat只加載一個web工程時,是沒有必要配置全局的resource的。
此外,還須要將mysql的Java驅動類以及其餘依賴包(若是有)放到tomcat的lib目錄下。
步驟2:
在web.xml中,配置<resource-ref>元素以在web應用中引用JNDI資源。
[html] view plain copy print?
步驟3:
在Web應用中使用數據源
[java] view plain copy print?
DBCP 是 Apache 軟件基金組織下的開源鏈接池實現,要使用DBCP數據源,須要應用程序應在系統中增長以下兩個 jar 文件:
Commons-dbcp.jar:鏈接池的實現
Commons-pool.jar:鏈接池實現的依賴庫
Tomcat 的鏈接池正是採用該鏈接池來實現的。該數據庫鏈接池既能夠與應用服務器整合使用,也可由應用程序獨立使用。
步驟1:
在類目錄下加入dbcp的配置文件:dbcp.properties
[plain] view plain copy print?
步驟2:
在獲取數據庫鏈接的工具類(如jdbcUtils)的靜態代碼塊中建立池:
[java] view plain copy print?
步驟3:
在應用中獲取鏈接
[java] view plain copy print?
c3p0是一個開源的JDBC鏈接池,它實現了數據源和JNDI綁定,支持JDBC3規範和JDBC2的標準擴展。c3p0通常是與hibernate,spring等框架一塊使用的,固然也能夠單獨使用。
dbcp沒有自動回收空閒鏈接的功能,c3p0有自動回收空閒鏈接功能。
使用c3p0須要導入c3p0.jar、mchange-commons-.jar,若是操做的是Oracle數據庫,那麼還須要導入c3p0-oracle-thin-extras-pre1.jar。
步驟1:
在類目錄下加入C3P0的配置文件:c3p0-config.xml
[html] view plain copy print?
還有更多可設置的參數,具體可查閱相關資料。
步驟2:
在獲取數據庫鏈接的工具類(如jdbcUtils)的靜態代碼塊中建立池
[java] view plain copy print?
步驟3:
在應用中獲取鏈接
[java] view plain copy print?
此外,還有其餘的鏈接池可供選擇,好比使用比較普遍的Proxool。Proxool是一種Java數據庫鏈接池技術。是sourceforge下的一個開源項目,這個項目提供一個健壯、易用的鏈接池,最爲關鍵的是這個鏈接池提供監控的功能,方便易用,便於發現鏈接泄漏的狀況。
proxool和 c3p0可以更好的支持高併發,可是在穩定性方面略遜於dpcp。
可根據項目的實際須要來選擇鏈接池。