首页 > 开发 > 综合 > 正文

有效发挥数据库的最大效率

2024-07-21 02:11:30
字体:
来源:转载
供稿:网友

有效发挥数据库的最大效率

snapbug

dec 2003 



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-else、exception,资源的管理也难免百密一疏。如同c中的内存泄漏问题,java系统也同样会面临崩溃的恶运。所以

 

数据库资源的管理依赖于应用系统本身,是不安全、不稳定的一种隐患。

 
2.2     jdbc连接池
在标准jdbc对应用的接口中,并没有提供资源的管理方法。所以,缺省的资源管理由应用自己负责。虽然在jdbc规范中,多次提及资源的关闭/回收及其他的合理运用。但最稳妥的方式,还是为应用提供有效的管理手段。所以,jdbc为第三方应用服务器(application server)提供了一个由数据库厂家实现的管理标准接口:连接缓冲(connection pooling)。引入了连接池( connection pool )的概念 ,也就是以缓冲池的机制管理数据库的资源。

 

jdbc最常用的资源有三类:

-          connection: 数据库连接。

-          statement: 会话声明。

-          resultset: 结果集游标。

  分别存在以下的关系 :



这是一种 ‘爷-父-子’ 的关系,对connection的管理,就是对数据库资源的管理。举个例子: 如果想确定某个数据库连接(connection)是否超时,则需要确定其(所有的)子statement是否超时,同样,需要确定所有相关的resultset是否超时;在关闭connection前,需要关闭所有相关的statement和resultset。

 

因此,连接池(connection pool)所起到的作用,不仅仅简单地管理connection,还涉及到 statement和resultset。

 
2.3     连接池(connectionpool)与资源管理
connectionpool以缓冲池的机制,在一定数量上限范围内,控制管理connection,statement和resultset。任何数据库的资源是有限的,如果被耗尽,则无法获得更多的数据服务。

 

在大多数情况下,资源的耗尽不是由于应用的正常负载过高,而是程序原因。

 

在实际工作中,数据资源往往是瓶颈资源,不同的应用都会访问同一数据源。其中某个应用耗尽了数据库资源后,意味其他的应用也无法正常运行。因此,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个,每个连接可同时提供250个statement,那么connectionpool最终为应用提供的并发statement总数为: 200 x 250 = 50,000个。这是个并发数字,很少有系统会突破这个量级。所以在本节的开始,指出资源的耗尽与应用程序直接管理有关。

 

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

 

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



 
3.     简单jdbc连接池的实现
根据第二章中原理机制,snap-connectionpool(一种简单快速的连接池工具,可在www.snapbug.net下载)按照部分的jdbc规范,实现了连接池所具备的对数据库资源有效管理功能。

 
3.1     体系描述
在jdbc规范中,应用通过驱动接口(driver interface)直接方法数据库的资源。为了有效、合理地管理资源,在应用与jdbc driver之间,增加了连接池: snap-connectionpool。并且通过面向对象的机制,使连接池的大部分操作是透明的。参见下图,snap-connectionpool的体系:



 

图中所示,通过实现jdbc的部分资源对象接口( connection, statement, resultset ),在 snap-connectionpool内部分别产生三种逻辑资源对象: pooledconnection, pooledstatement和 pooledresultset。它们也是连接池主要的管理操作对象,并且继承了jdbc中相应的从属关系。这样的体系有以下几个特点:

 

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

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

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

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

 
3.2     连接池集中管理connectionmanager
connectionpool是snap-connectionpool的连接池对象。在snap-connectionpool内部,可以指定多个不同的连接池(connectionpool)为应用服务。connectionmanager管理所有的连接池,每个连接池以不同的名称区别。通过配置文件适应不同的数据库种类。如下图所示:

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

 
3.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 here

 

rs.close();

st.close();

 

 


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

 
4.     小结
无论是snap-connectionpool还是其他的数据库连接池,都应当具备一下基本功能:

-          对源数据库资源的保护

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

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

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

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

注: 在网站 www.snapbug.net可免费下载snap-connectionpool及更详细的文档。

 
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表