數據庫-連接池

對於一個簡單的數據庫應用,由於對於數據庫的訪問不是很頻繁。這時可以簡單地在需要訪問數據庫時,就新創建一個連接,用完後就關閉它,這樣做也不會帶來什麼明顯的性能上的開銷。但是對於一個複雜的數據庫應用,情況就完全不同了。頻繁的建立、關閉連接,會極大的減低系統的性能,因爲對於連接的使用成了系統性能的瓶頸。

連接複用。通過建立一個數據庫連接池以及一套連接使用管理策略,使得一個數據庫連接可以得到高效、安全的複用,避免了數據庫連接頻繁建立、關閉的開銷。

對於共享資源,有一個很著名的設計模式:資源池。該模式正是爲了解決資源頻繁分配、釋放所造成的問題的。把該模式應用到數據庫連接管理領域,就是建立一個數據庫連接池,提供一套高效的連接分配、使用策略,最終目標是實現連接的高效、安全的複用。


數據庫連接池的基本原理是在內部對象池中維護一定數量的數據庫連接,並對外暴露數據庫連接獲取和返回方法。如:

外部使用者可通過getConnection 方法獲取連接,使用完畢後再通過releaseConnection 方法將連接返回,注意此時連接並沒有關閉,而是由連接池管理器回收,併爲下一次使用做好準備。

 

數據庫連接池技術帶來的優勢:

1. 資源重用

由於數據庫連接得到重用,避免了頻繁創建、釋放連接引起的大量性能開銷。在減少系統消耗的基礎上,另一方面也增進了系統運行環境的平穩性(減少內存碎片以及數據庫臨時進程/線程的數量)。

2. 更快的系統響應速度

數據庫連接池在初始化過程中,往往已經創建了若干數據庫連接置於池中備用。此時連接的初始化工作均已完成。對於業務請求處理而言,直接利用現有可用連接,避免了數據庫連接初始化和釋放過程的時間開銷,從而縮減了系統整體響應時間。

3. 新的資源分配手段

對於多應用共享同一數據庫的系統而言,可在應用層通過數據庫連接的配置,實現數據庫連接池技術,幾年錢也許還是個新鮮話題,對於目前的業務系統而言,如果設計中還沒有考慮到連接池的應用,那麼…….快在設計文檔中加上這部分的內容吧。某一應用最大可用數據庫連接數的限制,避免某一應用獨佔所有數據庫資源。

4. 統一的連接管理,避免數據庫連接泄漏

在較爲完備的數據庫連接池實現中,可根據預先的連接佔用超時設定,強制收回被佔用連接。從而避免了常規數據庫連接操作中可能出現的資源泄漏。一個最小化的數據庫連接池實現:

 

1.前言
數據庫應用,在許多軟件系統中經常用到,是開發中大型系統不可缺少的輔助。但如果對數據庫資源沒有很好地管理(如:沒有及時回收數據庫的遊標(ResultSet)Statement、連接 (Connection)等資源),往往會直接導致系統的穩定。這類不穩定因素,不單單由數據庫或者系統本身一方引起,只有系統正式使用後,隨着流量、用戶的增加,纔會逐步顯露。
在基於Java開發的系統中,JDBC是程序員和數據庫打交道的主要途徑,提供了完備的數據庫操作方法接口。但考慮到規範的適用性,JDBC只提供了最直接的數據庫操作規範,對數據庫資源管理,如:對物理連接的管理及緩衝,期望第三方應用服務器(Application Server)的提供。
本文,以JDBC規範爲基礎,介紹相關的數據庫連接池機制,並就如果以簡單的方式,實現有效地管理數據庫資源介紹相關實現技術。

 

2.連接池技術背景
2.1 JDBC
JDBC是一個規範,遵循JDBC接口規範,各個數據庫廠家各自實現自己的驅動程序(Driver),如下圖所示:

 

應用在獲取數據庫連接時,需要以URL的方式指定是那種類型的Driver,在獲得特定的連接後,可按照固定的接口操作不同類型的數據庫,如: 分別獲取Statement、執行SQL獲得ResultSet等,如下面的例子 :

import java.sql.*;

DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection dbConn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:oracle","username","password");
Statement st = dbConn.createStatement();
ResultSet rs = st.executeQuery("select * from demo_table");

…some data source operation in here

rs.close();
st.close();
dbConn.close();

在完成數據操作後,還一定要關閉所有涉及到的數據庫資源。這雖然對應用程序的邏輯沒有任何影響,但是關鍵的操作。上面是個簡單的例子,如果攙和衆多的if-elseexception,資源的管理也難免百密一疏。如同C中的內存泄漏問題,Java系統也同樣會面臨崩潰的惡運。所以數據庫資源的管理依賴於應用系統本身,是不安全、不穩定的一種隱患。

 

2.2 JDBC連接池
在標準JDBC對應用的接口中,並沒有提供資源的管理方法。所以,缺省的資源管理由應用自己負責。雖然在JDBC規範中,多次提及資源的關閉/回收及其他的合理運用。但最穩妥的方式,還是爲應用提供有效的管理手段。所以,JDBC爲第三方應用服務器(Application Server)提供了一個由數據庫廠家實現的管理標準接口:連接緩衝(connection pooling)。引入了連接池( Connection Pool )的概念 ,也就是以緩衝池的機制管理數據庫的資源。

JDBC最常用的資源有三類:
— Connection: 數據庫連接。
— Statement: 會話聲明。
— ResultSet: 結果集遊標。

分別存在以下的關係

 

這是一種的關係,對Connection的管理,就是對數據庫資源的管理。舉個例子: 如果想確定某個數據庫連接(Connection)是否超時,則需要確定其(所有的)子Statement是否超時,同樣,需要確定所有相關的 ResultSet是否超時;在關閉Connection前,需要關閉所有相關的StatementResultSet
因此,連接池(Connection Pool)所起到的作用,不僅僅簡單地管理Connection,還涉及到 StatementResultSet

 

2.3 連接池(ConnectionPool)與資源管理
ConnectionPool以緩衝池的機制,在一定數量上限範圍內,控制管理ConnectionStatementResultSet。任何數據庫的資源是有限的,如果被耗盡,則無法獲得更多的數據服務。
在大多數情況下,資源的耗盡不是由於應用的正常負載過高,而是程序原因。
在實際工作中,數據資源往往是瓶頸資源,不同的應用都會訪問同一數據源。其中某個應用耗盡了數據庫資源後,意味其他的應用也無法正常運行。因此,ConnectionPool的第一個任務是限制:每個應用或系統可以擁有的最大資源。也就是確定連接池的大小(PoolSize)
ConnectionPool的第二個任務:在連接池的大小(PoolSize)範圍內,最大限度地使用資源,縮短數據庫訪問的使用週期。許多數據庫中,連接(Connection)並不是資源的最小單元,控制Statement資源比Connection更重要。以Oracle爲例:
每申請一個連接(Connection)會在物理網絡(如 TCP/IP網絡)上建立一個用於通訊的連接,在此連接上還可以申請一定數量的Statement。同一連接可提供的活躍Statement數量可以達到幾百。在節約網絡資源的同時,縮短了每次會話週期(物理連接的建立是個費時的操作)。但在一般的應用中,多數按照2.1範例操作,這樣有10個程序調用,則會產生10次物理連接,每個Statement單獨佔用一個物理連接,這是極大的資源浪費。 ConnectionPool可以解決這個問題,讓幾十、幾百個Statement只佔用同一個物理連接, 發揮數據庫原有的優點。
通過ConnectionPool對資源的有效管理,應用可以獲得的Statement總數到達 :

(併發物理連接數)×(每個連接可提供的Statement數量)

例如某種數據庫可同時建立的物理連接數爲 200個,每個連接可同時提供250Statement,那麼ConnectionPool最終爲應用提供的併發Statement總數爲: 200 × 250 = 50,000個。這是個併發數字,很少有系統會突破這個量級。所以在本節的開始,指出資源的耗盡與應用程序直接管理有關。
對資源的優化管理,很大程度上依靠數據庫自身的JDBC Driver是否具備。有些數據庫的JDBC Driver並不支持ConnectionStatement之間的邏輯連接功能,如SQLServer,我們只能等待她自身的更新版本了。
對資源的申請、釋放、回收、共享和同步,這些管理是複雜精密的。所以,ConnectionPool另一個功能就是,封裝這些操作,爲應用提供簡單的,甚至是不改變應用風格的調用接口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章