`
阅读更多

六、基于JDBC的数据库连接池技术研究与应用

1、数据库连接池(connection pool)的工作原理

1)、基本概念及原理

JDBC作为一种数据库访问技术,具有简单易用的优点。但使用这种模式进行Web应用程序开发,存在很多问题:首先,每一次Web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的Web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

 

数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量、使用情况,为系统开发、测试及性能调整提供依据。

2)、服务器自带的连接池

JDBCAPI中没有提供连接池的方法。一些大型的WEB应用服务器如BEAWebLogicIBMWebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。

 

2、连接池关键问题分析

1)、并发问题

为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为Java语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如:

public synchronized Connection getConnection() 

2)、多数据库服务器和多用户

对于大型的企业级应用,常常需要同时连接不同的数据库(如连接OracleSybase)。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址(<poolName.url>)、用户名(<poolName.user>)、密码(<poolName.password>)等信息。如tx.url=172.21.15.1235000/tx_ittx.user=yangtx.password=yang321。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。

 

对于同一个数据库有多个用户使用不同的名称和密码访问的情况,也可以通过资源文件处理,即在资源文件中设置多个具有相同url地址,但具有不同用户名和密码的数据库连接信息。

3)、事务处理

我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。

Java语言中,Connection类本身提供了对事务的支持,可以通过设置ConnectionAutoCommit属性为false,然后显式的调用commitrollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。

4)、连接池的分配与释放

连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。

 

对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn,如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。

5)、连接池的配置与维护

连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。

 

可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。

 

如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。

3、连接池的实现

1)、连接池模型

连接池类是对某一数据库所有连接的“缓冲池”,主要实现以下功能:①从连接池获取或创建可用连接;②使用完毕之后,把连接返还给连接池;③在系统关闭前,断开所有连接并释放连接占用的系统资源;④还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。

 

连接池管理类是连接池类的外覆类(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, Stringpassword, 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的形式存取连接池对象的名字及连接池对象 

  private void loadDrivers(Properties props)//装载数据库驱动程序 
  private void createPools(Properties props)//根据属性文件提供的信息,创建一个或多个连接池 

  private DBConnectionManager()//私有构造函数,在其中调用初始化函数init() 
  private void init()//初始化连接池管理类的唯一实例,由私有构造函数调用 
  static synchronized public DBConnectionManager getInstance()//如果唯一的实例instance已经创建,直接返回这个实例;否则,调用私有构造函数,创建连接池管理类的唯一实例 

  public Connection getConnection(String name)//从名字为name的连接池对象//中得到一个连接 
  public Connection getConnection(String name, long time)//从名字为name 的连接池对象中取得一个连接,time是等待时间 

  public void freeConnection(String name, Connection con)//释放一个连接name是一个连接池对象的名 
  public synchronized void release()//释放所有资源 

} 

 

 3)、连接池使用

 

上面所实现的连接池在程序开发时如何应用到系统中呢?下面以Servlet为例说明连接池的使用。

Servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后,当服务器决定卸载一个servlet时,它首先调用该servlet destroy方法。 根据servlet的特点,我们可以在初始化函数中生成连接池管理类的唯一实例(其中包括创建一个或多个连接池)。如:

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

 

然后就可以在service方法中通过连接池名称使用连接池,执行数据库操作。最后在destroy方法中释放占用的系统资源,如:   

public void destroy() {  

connMgr.release(); 

super.destroy();  

}

 

4 JDBC连接池的资源管理

 

1)、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)、连接池(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总数到达

(并发物理连接数) x (每个连接可提供的Statement数量)

 

例如某种数据库可同时建立的物理连接数为 200个,每个连接可同时提供250Statement,那么ConnectionPool最终为应用提供的并发Statement总数为: 200 x 250 = 50,000个。这是个并发数字,很少有系统会突破这个量级。所以在本节的开始,指出资源的耗尽与应用程序直接管理有关。

 

对资源的优化管理,很大程度上依靠数据库自身的JDBC Driver是否具备。有些数据库的JDBC Driver并不支持ConnectionStatement之间的逻辑连接功能,如SQLServer,我们只能等待她自身的更新版本了。

 

对资源的申请、释放、回收、共享和同步,这些管理是复杂精密的。所以,ConnectionPool另一个功能就是,封装这些操作,为应用提供简单的,甚至是不改变应用风格的调用接口。

 

5、简单JDBC连接池的实现

根据第二章中原理机制,Snap-ConnectionPool(一种简单快速的连接池工具)按照部分的JDBC规范,实现了连接池所具备的对数据库资源有效管理功能。

1)、体系描述

JDBC规范中,应用通过驱动接口(Driver Interface)直接方法数据库的资源。为了有效、合理地管理资源,在应用与JDBC Driver之间,增加了连接池: Snap-ConnectionPool。并且通过面向对象的机制,使连接池的大部分操作是透明的。

 

通过实现JDBC的部分资源对象接口( Connection, Statement, ResultSet ),在 Snap-ConnectionPool内部分别产生三种逻辑资源对象: PooledConnection, PooledStatement PooledResultSet。它们也是连接池主要的管理操作对象,并且继承了JDBC中相应的从属关系。这样的体系有以下几个特点:

 

-透明性。在不改变应用原有的使用JDBC驱动接口的前提下,提供资源管理的服务。应用系统,如同原有的 JDBC,使用连接池提供的逻辑对象资源。简化了应用程序的连接池改造。

 

-资源封装。复杂的资源管理被封装在 Snap-ConnectionPool内部,不需要应用系统过多的干涉。管理操作的可靠性、安全性由连接池保证。应用的干涉(如:主动关闭资源),只起到优化系统性能的作用,遗漏操作不会带来负面影响。

 

-资源合理应用。按照JDBC中资源的从属关系,Snap-ConnectionPool不仅对Connection进行缓冲处理,对Statement也有相应的机制处理。在2.3已描述,合理运用ConnectionStatement之间的关系,可以更大限度地使用资源。所以,Snap-ConnectionPool封装了Connection资源,通过内部管理PooledConnection,为应用系统提供更多的Statement资源。

 

-资源连锁管理。Snap-ConnectionPool包含的三种逻辑对象,继承了JDBC中相应对象之间的从属关系。在内部管理中,也依照从属关系进行连锁管理。例如:判断一个Connection是否超时,需要根据所包含的Statement是否活跃;判断Statement也要根据ResultSet的活跃程度。

 

2)、连接池集中管理ConnectionManager

ConnectionPoolSnap-ConnectionPool的连接池对象。在Snap-ConnectionPool内部,可以指定多个不同的连接池(ConnectionPool)为应用服务。ConnectionManager管理所有的连接池,每个连接池以不同的名称区别。通过配置文件适应不同的数据库种类。

 

通过ConnectionManager,可以同时管理多个不同的连接池,提供通一的管理界面。在应用系统中通过ConnectionManager和相关的配置文件,可以将凌乱散落在各自应用程序中的数据库配置信息(包括:数据库名、用户、密码等信息),集中在一个文件中。便于系统的维护工作。

 

3)、连接池使用范例

2.1的标准JDBC的使用范例,改为使用连接池,结果如下:

import java.sql.*;
import net.snapbug.util.dbtool.*;
…
..ConnectionPool dbConn = ConnectionManager
                   .getConnectionPool("testOracle" );
Statement st = dbConn.createStatement();
ResultSet rs = st.executeQuery( 
             “select * from demo_table” );
…
some data source operation 
     in herers.close();st.close();

 

在例子中,Snap-ConnectionPool封装了应用对Connection的管理。只要改变JDBC获取Connection的方法,为获取连接池(ConnectionPool)(粗体部分),其他的数据操作都可以不做修改。按照这样的方式,Snap-ConnectionPool可帮助应用有效地管理数据库资源。如果应用忽视了最后资源的释放: rs.close() st.close(),连接池会通过超时(time-out)机制,自动回收。

 

4)、小结

无论是Snap-ConnectionPool还是其他的数据库连接池,都应当具备一下基本功能:

-对源数据库资源的保护

-充分利用发挥数据库的有效资源

-简化应用的数据库接口,封闭资源管理。

-对应用遗留资源的自动回收和整理,提高资源的再次利用率。

 

在这个前提下,应用程序才能投入更多的精力于各自的业务逻辑中。数据库资源也不再成为系统的瓶颈。

 

分享到:
评论

相关推荐

    数据库实验JDBC连接数据库.docx

    选课序号:36 选课序号:36 大连海事大学 数据库原理课程实验报告 (2010-2011学年第二学期) 实验八 JDBC连接数据库 班 级: 智能一班 学 号: ********** 姓 名: 徐维坚 指导教师: *** 成 绩: 2012年 6月 13日 ...

    JDBC总结——事务

    文章目录事务一、事务的基本介绍1、概念2、操作3、操作实例4、MySQL数据库中默认自动提交二、事务的四大特征三、事务的隔离级别1、概念2、存在的问题3、隔离级别四、Jdbc事务控制1、概述2、控制事务的API:3、核心...

    2.2-JDBC思维导图 .emmx

    大数据学习之第二阶段Hadoop(第二篇)--JDBC思维导图+复习知识点总结

    JDBC访问数据库的步骤

    JDBC编程步骤总结: 1. Load the Driver:Class.forName(); 2. Connect the DateBase: DriveManager.getConnection() 3. Execute the SQL: (1) Connection.createStatement() Connection.prepareStatement(sql) ...

    基于JSP+JAVABEAN+JDBC图书管理系统

    基于JSP+JAVABEAN+JDBC图书管理系统 摘 要 .........................................................1 目 录 .........................................................2 第一章 绪论 ..................

    javaee 实验报告 实验一 JSP+Servlet+Javabean+jdbc-基于MVC模式的数据库的应用

    实验一 JSP+Servlet+Javabean+jdbc-基于MVC模式的数据库的应用 实验二 JSF+JPA实现用户注册 实验三 struts+spring+hibernate框架访问数据库的应用 实验四 使用WebService和EJBean访问数据库的应用

    javaweb学习总结——使用JDBC处理MySQL大数据

    本篇文章主要介绍了JDBC处理MySQL大数据,有时是需要用程序把大文本或二进制数据直接保存到数据库中进行储存的,非常具有实用价值,需要的朋友可以参考下。

    实验二 JSP表单开发及访问数据库

    一、实验目的 1.掌握JSP表单的开发方法。 2.熟悉JDBC技术和使用JDBC连接各种数据库。 二、实验学时 2H 三、实验性质 综合性实验

    groovy将JDBC中oracle存储过程游标转换为多层json

    本例是我工作中的一些实操例子,亦是我工作日志,记录在此,既可作为我自己的总结,也可以此分享给同行借鉴。 入参是字符串格式的xml,目的是解析xml节点值,作为数据库检索where条件,检索出数据库记录,利用四个...

    一步一步学会JDBC

    文章目录一、JDBC基本知识二、java中与JDBC相关的接口三、JDBC编程的步骤1.步骤总览2.重点说下前三步2.1注册驱动2.2.获取Connection连接:DriverManager.getConnection方法2.3.获取数据库操作对象:通过Connection...

    网上考试系统总结

    开发平台:eclipse3.1 数据库:Oracle 9i 总结中包括: 一、该系统主要解决的问题 二、功能 三、开发中遇到的问题及解决方案 四、版本 五、总结 具体代码可以从 ...

    android使用mysql的方法总结

    在Android工程中要使用jdbc的话,要导入jdbc的外部jar包,因为在Java的jdk中并没有jdbc的api,我使用的jar包是mysql-connector-java-5.1.18-bin.jar包,网络上有使用mysql-connector-java-5.1.18-b

    Java 基础核心总结 +经典算法大全.rar

    -、Iterator Iterable ListIterator 二、Map 和 Collection 接口Map 集合体系详解 HashMap LinkedHashMap TreeMap WeakHashMap Hashtable Collection 集合体系详解 Set 接口 AbstractSet 抽象类SortedSet 接口...

    设备维修管理系统,JavaWeb 项目,使用原生servlet 和 JDBC。.zip

    持续实践与反思:通过实际操作项目,不断反思和总结,形成自己的技术见解和经验。 参与社区讨论:与同行交流心得,共同成长,拓宽视野。际操作项目,不断反思和总结,形成自己的技术见解和经验。 参与社区讨论:与...

    教学在线留言答疑系统,JavaWeb基础,servlet jsp filter,原生jdbc.zip

    持续实践与反思:通过实际操作项目,不断反思和总结,形成自己的技术见解和经验。 参与社区讨论:与同行交流心得,共同成长,拓宽视野。际操作项目,不断反思和总结,形成自己的技术见解和经验。 参与社区讨论:与...

    Java面试总结.zip

    本次分享的资源涵盖了Java面试的各个方面,从基础知识到高级技术,从数据库到框架应用,都做了深入的探讨和总结。具体内容包括: Java基础知识点:包括数据类型、面向对象特性、异常处理、集合框架等。 Java核心...

    Java面试知识总结.zip

    本次分享的资源涵盖了Java面试的各个方面,从基础知识到高级技术,从数据库到框架应用,都做了深入的探讨和总结。具体内容包括: Java基础知识点:包括数据类型、面向对象特性、异常处理、集合框架等。 Java核心...

    Java语言基础下载

    第二十章:高级JDBC 337 学习目标 337 使用DDL,DML语言对数据库进行基本操作 338 查询数据库里的数据 339 预编译语句(PreparedStatement) 340 使用事务 341 事务的级别控制 343 使用存储过程 345 操作元数据 347 ...

Global site tag (gtag.js) - Google Analytics