基於JDBC的資料庫連接池技術研究與設計

來源:互聯網
上載者:User
設計|資料|資料庫|資料庫連接    本文介紹了基於JDBC的資料庫連接池的工作原理,闡述了串連池技術的交易處理、多資料庫伺服器等各項關鍵技術,提出了一個高效的串連池管理原則,最後詳細說明了資料庫連接池應用的具體實現過程。

  關鍵詞 JDBC; 資料庫; 串連池; 交易處理

  隨著資訊技術的高速發展與廣泛應用,資料庫技術在資訊技術領域中的位置越來越重要,尤其是網路應用和電子商務的迅速發展,都需要資料庫支援人員動態Web網站的運行,而傳統的開發模式是:首先在主程式(如Servlet、Beans)中建立資料庫連接;然後進行SQL操作,對資料庫中的對象進行查詢、修改和刪除等操作;最後斷開資料庫連接。使用這種開發模式,對於一個簡單的資料庫應用,由於資料庫的訪問不是很頻繁,只需要在訪問資料庫時建立一個串連,用完後就關閉它,這樣做不會明顯的增大系統的開銷。但是對於一個複雜的資料庫應用,情況就完全不同:頻繁的建立、關閉資料庫,會極大的降低系統的效能,增大系統的開銷,甚至成為系統的瓶頸。另外使用這種傳統的模式,還必須管理資料庫的每一個串連,以確保他們能正確關閉,如果出現程式異常而導致某些串連未能關閉,將引起資料庫系統中的記憶體泄露,最終不得不重啟資料庫。因此採用運行速度更快、資料庫訪問效率更高的資料庫技術,以提高系統的運行效率將是至關重要的。

  為瞭解決這一問題,在JDBC2.0中提出了JDBC串連池技術,通過在客戶之間共用一組串連,而不是在它們需要的時候再為它們產生,這樣就可以改善資源使用,提高應用程式的響應能力。

  JDBC 概述

  JDBC(Java Database Connectivity,Java資料庫連接)是一種用於執行SQL語句的JavaAPI,可以為多種關係型資料庫(如Oracle、Sybase、SQL Server、Access等)提供統一提供者,它由一組Java語言編寫的類和介面組成,使資料庫開發人員能夠用標準JavaAPI編寫資料庫應用程式。

  串連池技術

  1、串連池原理

  串連池技術的核心思想是:串連複用,通過建立一個資料庫連接池以及一套串連使用、分配、管理原則,使得該串連池中的串連可以得到高效、安全的複用,避免了資料庫連接頻繁建立、關閉的開銷。另外,由於對JDBC中的原始串連進行了封裝,從而方便了資料庫應用對於串連的使用(特別是對於交易處理),提高了開發效率,也正是因為這個封裝層的存在,隔離了應用的本身的處理邏輯和具體資料庫訪問邏輯,使應用本身的複用成為可能。串連池主要由三部分組成(如圖1所示):串連池的建立、串連池中串連的使用管理、串連池的關閉。下面就著重討論這三部分及串連池的配置問題。

圖1 串連池模式

  1.1 串連池的建立

  應用程式中建立的串連池其實是一個靜態。所謂靜態串連池是指串連池中的串連在系統初始化時就已指派好,且不能隨意關閉串連。Java中提供了很多容器類可以方便的構建串連池,如:Vector、Stack、Servlet、Bean等,通過讀取串連屬性檔案Connections.properties與資料庫執行個體建立串連。在系統初始化時,根據相應的配置建立串連並放置在串連池中,以便需要使用時能從串連池中擷取,這樣就可以避免串連隨意的建立、關閉造成的開銷。

  1.2 串連池的管理

  串連池管理原則是串連池機制的核心。當串連池建立後,如何對串連池中的串連進行管理,解決好串連池內串連的分配和釋放,對系統的效能有很大的影響。串連的合理分配、釋放可提高串連的複用,降低了系統建立新串連的開銷,同時也加速了使用者的訪問速度。下面介紹串連池中串連的分配、釋放策略。

  串連池的分配、釋放策略對於有效複用串連非常重要,我們採用的方法是一個很有名的設計模式:Reference Counting(引用記數)。該模式在複用資源方面應用的非常廣泛,把該方法運用到對於串連的分配釋放上,為每一個資料庫連接,保留一個引用記數,用來記錄該串連的使用者的個數。具體的實現方法是:

  當客戶請求資料庫連接時,首先查看串連池中是否有空閑串連(指當前沒有分配出去的串連)。如果存在空閑串連,則把串連分配給客戶並作相應處理(即標記該串連為正在使用,引用計數加1)。如果沒有空閑串連,則查看當前所開的串連數是不是已經達到maxConn(最大串連數),如果沒達到就重新建立一個串連給請求的客戶;如果達到就按設定的maxWaitTime(最大等待時間)進行等待,如果等待maxWaitTime後仍沒有空閑串連,就拋出無空閑串連的異常給使用者。

  當客戶釋放資料庫連接時,先判斷該串連的引用次數是否超過了規定值,如果超過就刪除該串連,並判斷當前串連池內總的串連數是否小於minConn(最小串連數),若小於就將串連池充滿;如果沒超過就將該串連標記為開放狀態,可供再次複用。可以看出正是這套策略保證了資料庫連接的有效複用,避免頻繁地建立、釋放串連所帶來的系統資源開銷。

  1.3 串連池的關閉

  當應用程式退出時,應關閉串連池,此時應把在串連池建立時向資料庫申請的連線物件統一歸還給資料庫(即關閉所有資料庫連接),這與串連池的建立正好是一個相反過程。

  1.4 串連池的配置

  資料庫連接池中到底要放置多少個串連,才能使系統的效能更佳,用minConn和maxConn來限制。minConn是當應用啟動的時候串連池所建立的串連數,如果過大啟動將變慢,但是啟動後響應更快;如果過小啟動加快,但是最初使用的使用者將因為串連池中沒有足夠的串連不可避免的延緩了執行速度。因此應該在開發的過程中設定較小minConn,而在實際應用的中設定較大minConn。maxConn是串連池中的最大串連數,可以通過反覆實驗來確定此飽和點。為此在串連池類ConnectionPool中加入兩個方法getActiveSize()和getOpenSize(),ActiveSize 表示某一時間有多少串連正被使用,OpenSize表示串連池中有多少串連被開啟,反映了串連池使用的峰值。將這兩個值在日誌資訊中反應出來, minConn的值應該小於平均ActiveSize,而maxConn的值應該在activeSize和OpenSize之間。

  2、串連池的關鍵技術

  2.1 交易處理

  前面討論的是關於使用資料庫連接進行普通的資料庫訪問。對於交易處理,情況就變得比較複雜。因為事務本身要求原則性的保證,此時就要求對於資料庫的操作符合"All-All-Nothing"原則,即要麼全部完成,要麼什麼都不做。如果簡單的採用上述的串連複用的策略,就會發生問題,因為沒有辦法控制屬於同一個事務的多個資料庫操作方法的動作,可能這些資料庫操作是在多個串連上進行的,並且這些串連可能被其他非事務方法複用。Connection本身具有提供了對於事務的支援,可以通過設定Connection的AutoCommit屬性為false,顯式的調用 commit或rollback方法來實現。但是要安全、高效的進行串連複用,就必須提供相應的事務支援機制。方法是:採用顯式的事務支撐方法,每一個事務獨佔一個串連。這種方法可以大大降低對於交易處理的複雜性,並且又不會妨礙串連的複用。

  串連管理服務提供了顯式的事務開始、結束(commit或rollback)聲明,以及一個事務註冊表,用於登記事務發起者和事務使用的串連的對應關係,通過該表,使用事務的部分和串連管理部分就隔離開,因為該表是在運行時根據實際的調用情況動態產生的。事務使用的串連在該事務運行中不能被複用。在實現中,使用者標識是通過使用者所在的線程來標識的。後面的所有對於資料庫的訪問都是通過尋找該註冊表,使用已經分配的串連來完成的。當事務結束時,從註冊表中刪除相應表項。

  2.2 封裝

  從上面的論述可以看出,普通的資料庫方法和事務方法對於串連的使用(分配、釋放)是不同的,為了便於使用,對外提供一致的操作介面,我們對串連進行了封裝:普通串連和事務串連,並利用了Java中的強大的物件導向特性:多態。普通串連和事務串連均實現了一個DbConnection介面,對於介面中定義的方法,分別根據自己的特點作了不同的實現,這樣在對於串連的處理上就非常的一致了。

  2.3 並發

  為了使串連管理服務有更大的通用性,我們必須要考慮到多線程環境,即並發問題。在一個多線程的環境下,必須要保證串連管理自身資料的一致性和串連內部資料的一致性,在這方面Java提供很好的支援(synchronized關鍵字),這樣就很容易使串連管理成為安全執行緒的。

  2.4 多資料庫伺服器

  在實際應用中,應用程式常常需要訪問多個不同的資料庫。如何通過同一個串連池訪問不同的資料庫,是應用程式需要解決的一個核心問題。下面介紹一種解決的途徑:

  首先,定義一個資料庫連接池參數的類,定義了資料庫的JDBC驅動程式類名,串連的URL以及使用者名稱口令等等一些資訊,該類是用於初始化串連池的參數:

public class ConnectionParam implements Serializable{
 //各初始化參數的定義
}
  其次是串連池的工廠類ConnectionFactory,通過該類將一個串連池對象與一個名稱對應起來,使用者通過該名稱就可以擷取指定的串連池對象,實現的主要代碼如下:

public class ConnectionFactory{
 static Hashtable connectionPools = //用來儲存資料來源名和串連池對象的關係
 public static DataSource lookup(String dataSourceName) throws
 NameNotFoundException{
  //尋找名字為dataSourceName的資料來源
 }

 public static DataSource bind(String name, ConnectionParam param)
 throws Exception
 //將名字name與使用param初始化的串連池對象綁定
}

public static void unbind(String name) throws NameNotFound
Exception{
 //將與名字name綁定的串連池對象刪除
}

  串連池應用的實現

  一個完整的串連池應用程式套件括三個部分:DBConnectionPool類,負責從串連池擷取(或建立)串連、將串連返回給串連池、系統關閉時關閉所有串連釋放所有資源;DBConnectionManager類,負責裝載和註冊JDBC驅動、根據屬性檔案中定義的屬性建立DBConnectionPool、跟蹤應用程式對串連池的引用等;應用程式對串連池的使用。

  本文實現的資料庫連接池包括一個管理類DBConnectionManager,負責提供與多個串連池對象(DBConnectionPool類)之間的介面。每一個串連池對象管理一組封裝過的JDBC連線物件Conn,封裝過的JDBC連線物件Conn可以被任意數量的Model層的組件共用。

  類Conn 的設計很簡單,如下所示:

Class Conn {
 Private java. sgl .Connection con; //資料庫連接對象
 Public Boolean inUse ; //是否被使用
 Public long lastAccess; //最近一次釋放該串連的時間
 Public int useCount; // 被使用次數
}
  下面是實現串連池的主要代碼:

// 初始化資料庫連接池

public static synchronized void FastInitPool()
throws Exception {
 try { Class.forName(driver);
  for (int i=0; i<size; i++) {
   Connection con = createConnection();
   if (con!=null) addConnection(con);
  } } }

// 向串連池對象中添加資料庫連接

private static void addConnection(Connection con) {
 if (pool=null||pool1=null) {
  pool=new Vector(size);
  pool1=new Vector(size); }
 pool.addElement(con);
 pool1.addElement("false"); }

// 擷取資料庫連接

public static synchronized Connection getConn()
throws Exception {
 Connection conn = null;
 try { if (driver = null)
  FastInitPool();
  // 獲得一個可用的(閒置)串連
 .for (int i = 0; i < pool.size(); i++) {
  conn = (Connection)pool.elementAt(i);
  if (pool1.elementAt(i)=="false") {
   pool1.set(i,"true");
   //System.out.println("從串連池中擷取第"+(i+1)+"個空閑串連");
   return conn;
  }
 }
 //如果沒有可用串連,且已有串連數小於最大串連數限制,則建立並增加一個新串連到串連池
 conn = createConnection();
 pool.addElement(conn);
 pool1.addElement("true");
 // System.out.println(" 所有串連都在使用,在串連池中再建立一個新串連");
}

catch (Exception e) {
 System.err.println(e.getMessage());
 throw new Exception(e.getMessage());
}
return conn; //返回一個有效新串連
}

public Connection getConnection(String strDriver, String strUrl, String strUserName, String strPassWord)
throws SQLException{
 try{ Class.forName(strDriver);
  conn = DriverManager.getConnection(strUrl, strUserName, strPassWord); }
 return conn; }
  結束語

  當前Web應用程式廣泛採用B/S結構,其並發性決定了多使用者同時訪問資料庫的問題。本文闡述的基於JDBC的資料庫連接池技術已成功應用於基於Web的高職教學系統開發中,並建立了資料庫連接池執行個體來說明和證實串連池的存取方法。只有充分運用串連池訪問技術,才能提高資料庫的訪問效率,改善Web應用,從而減少系統開銷,大大提高整個Web應用系統的運行效率。

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。