Java中数据库连接池原理机制的详细讲解

上一篇 / 下一篇  2009-04-13 15:15:18 / 个人分类:测试相关知识

)R0CNdxI'EU0连接池的基本工作原理51Testing软件测试网$]e9\}1juW

51Testing软件测试网:j b2M5R^f#qh

  1、基本概念及原理

-sL:t(cLJ"CV0

NW{_Wv*S%b D0  由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配?释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量?使用情况,为系统开发?测试及性能调整提供依据。51Testing软件测试网A4qAGo7sqP:C"K

1vK(` {,d8D6r0  2、服务器自带的连接池

/j%Z,DB_051Testing软件测试网-HE2s1| q

  JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。51Testing软件测试网&v@_Z3cZ"{v ]

V/l+p3R#e.uw |M0  连接池关键问题分析

*{WAh@'KO;l&T0

-`x1|TR3u2Z Y)r W0  1、并发问题

9e0W-A/Wn&D051Testing软件测试网 k s$y c*h

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

|'Y8L.g5b9E sv0Z+yb0

HVZI \8T0  public synchronized Connection getConnection()51Testing软件测试网9@.x5mUdMm J$Ex

u v(Rc A0  2、多数据库服务器和多用户

W F5P_n*N7MP051Testing软件测试网2P;?ob*Q$U7g)L`$yr

  对于大型的企业级应用,常常需要同时连接不同的数据库(如连接Oracle和Sybase)。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址()?用户名()?密码()等信息。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。51Testing软件测试网+F f,h*HK!g

51Testing软件测试网u]J4V\/V"g$J(^

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

0Ag#l)W R-?VE/|051Testing软件测试网V*ZKyY

  3、事务处理

}1Z Ce]`wU}8sA051Testing软件测试网A5@9N{ _d8S[7i

  我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。51Testing软件测试网 XC F2M g%M

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

X9p J2?5GT\0

4u&i6P![t7wf4r"V0  4、连接池的分配与释放51Testing软件测试网{ _.A"uA

51Testing软件测试网m X8Sxo8^9jX_

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

N1y5z"~2H w.P0

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

_6c8K+]8G0

U2M8M+~6s4mxk7M0  5、连接池的配置与维护

8BE%t2^Ts#i*[A-A0

H`E|~+P0  连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。

D"?*N\+Y|'P051Testing软件测试网R x7y"J%_6Y

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

51Testing软件测试网 P-tAE#J%H

  连接池的实现

+xQ"mmh B3B0

~$S fd:{N6z)@7]0  1、连接池模型

F#oc c6B h[` e7J0

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

*u Tb&N:tp;v;fU0  连接池管理类是连接池类的外覆类(wrapper),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理,具有以下功能:①装载并注册特定数据库的JDBC驱动程序;②根据属性文件给定的信息,创建连接池对象;③为方便管理多个连接池对象,为每一个连接池对象取一个名字,实现连接池名字与其实例之间的映射;④跟踪客户使用连接情况,以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于安全性问题,需要不同的用户使用不同的名称和密码。

-H,p}:c _O9s i9f0

bIN{6C7pG'hyj1D0  2、连接池实现

"\8r9k L$F?B vH8["k051Testing软件测试网3Ic+UHnG;y#ip

  下面给出连接池类和连接池管理类的主要属性及所要实现的基本接口:51Testing软件测试网*qM N,F&B ru*k

*k_0u9v.qZ3R0  public class DBConnectionPool implements TimerListener{

1JB?/Fw9i9I QM)s051Testing软件测试网_6C"HX)YP3p6w

  private int checkedOut;//已被分配出去的连接数51Testing软件测试网s#hbD1z)r;Og(T:t i

51Testing软件测试网tNp@\m7F

  private ArrayList freeConnections=new ArrayList();

Z1CNOX;{Z~051Testing软件测试网?"`{9n8^Dwu

  //容器,空闲池,根据//创建时间顺序存放已创建但尚未分配出去的连接

7Q)_F0n!Y{0

`1~+lU8g!ri0  private int minConn;//连接池里连接的最小数量

WBp8?0B'M @.H4W051Testing软件测试网y GW5\4H2n

  private int maxConn;//连接池里允许存在的最大连接数51Testing软件测试网dG8Pjr-Qe

51Testing软件测试网&Ck@hOtSX

  private String name;//为这个连接池取个名字,方便管理

/I8beh1}0bI? M0

*v(@yG+y{+ufU9a0  private String password;//连接数据库时需要的密码51Testing软件测试网-ZKN9rRE

51Testing软件测试网sVo[6^G

  private String url;//所要创建连接的数据库的地址

S%^$MI/a6L:avb4^7M051Testing软件测试网W-w,NWw&^ w5k

  private String user;//连接数据库时需要的用户名51Testing软件测试网 N&^?W [6}q

})l uG1K/XZ-f2]0  public Timer timer;//定时器

M.Q3Fm-uz3zR%T5Z:v0

(d6}H j)pDfp3~I/Ed9u0  public DBConnectionPool(String name,String URL,String user,

)|x8q-z%p!@6cr%d9XDP0

5b4P ScSa ?0  String password,int maxConn)//公开的构造函数51Testing软件测试网]H ZM5C5i

51Testing软件测试网/N.o,k$@}2g`

  public synchronized void freeConnection(Connection con)51Testing软件测试网W[)v x0C X f~)]I:w

51Testing软件测试网O.F#rb"z1[.c h-EN)I

  //使用完毕之后,把连接返还给空闲池51Testing软件测试网r*W2FUJF

S{U G"D5j5_2Q0  public synchronized Connection getConnection(long timeout)

?0d cs'l@ZN1G5fD0

![:t R%T U]6]0  //得到一个连接,timeout是等待时间51Testing软件测试网 H[Fm l

"W\ `'WuhN8^0  public synchronized void release()51Testing软件测试网s{US4a'I#q2p P

3K+W9bl%pSI?0  //断开所有连接,释放占用的系统资源51Testing软件测试网*uU-|,v\a M

51Testing软件测试网 I{K+X oD6z

  private Connection newConnection()

5a c#L'T5E }8e$`4p051Testing软件测试网A*s!l%uc/?3nZ1a f#T

  //新建一个数据库连接51Testing软件测试网 KP9z+\m x X q

51Testing软件测试网,EC.Pf5O6FV(k

  public synchronized void TimerEvent()

f G_.b4zH0

c;F$l P(A d _(t0  //定时器事件处理函数

}p:{r8c-Nn S8E hO"K0

@o.l.]%F0  }51Testing软件测试网$A*f[;F Q HE O#@

51Testing软件测试网6jrnG{@$jU4C$u

  public class DBConnectionManager {

Bf2T B `4_Z0

9Y?k%n Wdvt6O2`m0  static private DBConnectionManager instance;

FSw7K)xw{#h^&]]ZB0

2L9D f e\8iMl i0  //连接池管理类的唯一实例51Testing软件测试网3Z*FX"z V

N K1{+R1W`'J8y0  static private int clients;//客户数量

)|8VioDPfq0

\sO)l,i4pa0  private ArrayList drivers=new ArrayList();

sI"am3` e6M%CFHlAB:]051Testing软件测试网-N/kM-T4u

  //容器,存放数据库驱动程序51Testing软件测试网*d7M3F#o4T

51Testing软件测试网-DL3~1h3^6uz6D

  private HashMap pools = new HashMap();

,I|4WT&s({M0u1vF0

4kqAhY7t]C0  //以name/value的形式存取连接池对象的名字及连接池对象

+]8z&b0ZPr6\ C051Testing软件测试网1i\D-i sz,w*yiT

  static synchronized public DBConnectionManager getInstance()

4K@$c`ti0

.Z lu?3G.lv-O8|0  /**如果唯一的实例instance已经创建,直接返回这个实例;否则,调用私有构造函数,

(Z+Bet | P m5e,W051Testing软件测试网'I3` ]:^f-K^C

  创建连接池管理类的唯一实例*/

N)rgU }b0

0[3V4j6b G3Ekt0  private DBConnectionManager()

pr3W'y:I051Testing软件测试网7F;\ I^_E

  //私有构造函数,在其中调用初始化函数init()51Testing软件测试网XCac-o"C"m

]N E cuH O y0  public void freeConnection(String name,Connection con)

B;Mg7H0b1A1i051Testing软件测试网(v3i;G-W2Elv

  //释放一个连接,name是一个连接池对象的名字51Testing软件测试网+y]'| m2d

^ B0ie;v'nC$`aM0  public Connection getConnection(String name)51Testing软件测试网Fc?JA

51Testing软件测试网*G]!QG,x SA"g

  //从名字为name的连接池对象中得到一个连接

.\,|:?Le051Testing软件测试网2`JP(W A:n7|?n

  public Connection getConnection(String name,long time)51Testing软件测试网^ n`2k)t*C'_6Sxvo

51Testing软件测试网}8iq%~5\3T9o0Lt1r

  //从名字为name的连接池对象中取得一个连接,time是等待时间

U,iLaP ?0J0

:S2r"|9hnS.T0  public synchronized void release()//释放所有资源51Testing软件测试网MMr&X$q#~.r}SG

G2O5W2o U:@7K9d/UG:[5?0  private void createPools(Properties props)

eo5x+Ga LI-a7Y.P;T,R0

t9uTO"PK0  //根据属性文件提供的信息,创建一个或多个连接池

;yF@5e M:yc051Testing软件测试网/b:Z5CN Vh3h8f3n t

  private void init()//初始化连接池管理类的唯一实例,由私有构造函数调用

^ A2h[ s*U6F051Testing软件测试网aWi B&ZJv7cU S D

  private void loadDrivers(Properties props)//装载数据库驱动程序51Testing软件测试网Opj/V]5b

X;l&e(VC*JAdw0  }

n-u?i-ezt(\051Testing软件测试网;unO-y9CBT

  3、连接池使用51Testing软件测试网q'I']9r1k

51Testing软件测试网(bz5Y {*\Z'ml Y

  上面所实现的连接池在程序开发时如何应用到系统中呢?下面以Servlet为例说明连接池的使用。51Testing软件测试网:cc?C]

&v:S*fz*O},}1]/w0  Servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后,当服务器决定卸载一个servlet时,它首先调用该servlet的destroy方法。51Testing软件测试网$r_ eh'[(B:s

51Testing软件测试网 ov3a(zl3e

  根据servlet的特点,我们可以在初始化函数中生成连接池管理类的唯一实例(其中包括创建一个或多个连接池)。如:

4u0| GW4u:q dL`051Testing软件测试网#]R#^0hcnBv

  public void init() throws ServletException51Testing软件测试网jb9q/WW$CE

51Testing软件测试网I7Pe+i!n~e ^Z_

  {51Testing软件测试网%W"N2?JYM

#]"nEiH0  connMgr=DBConnectionManager.getInstance();51Testing软件测试网tw"G'f$oK `o9O8NA

9SS0F$p9s#ZA+Vm0  }

+[q-T;V sT051Testing软件测试网G,`r6r PwOO

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

}0LO1y3u6sZ051Testing软件测试网1Qj q'KbbU _m

  public void destroy(){

"sj+I;CCzD-V0

h K)v0?H0  connMgr.release();

c n!l*^8?&z v`9h0

Y/E:esn0  super.destroy();51Testing软件测试网4rk-b"M+y

b X1Y6TQ g`0  }

2p5v$Q\v051Testing软件测试网yrTf?)e+x@

  结束语

$t!z E1u X6MQ6^051Testing软件测试网n(i C}6Z,z5W/I

  在使用JDBC进行与数据库有关的应用开发中,数据库连接的管理是一个难点。很多时候,连接的混乱管理所造成的系统资源开销过大成为制约大型企业级应用效率的瓶颈。对于众多用户访问的Web应用,采用数据库连接技术的系统在效率和稳定性上比采用传统的其他方式的系统要好很多。本文阐述了使用JDBC访问数据库的技术?讨论了基于连接池技术的数据库连接管理的关键问题并给出了一个实现模型。文章所给出的是连接池管理程序的一种基本模式,为提高系统的整体性能,在此基础上还可以进行很多有意义的扩展。

/ucL4])E+G4DI0

TAG:

 

评分:0

我来说两句

gezj2006

gezj2006

做最好的自己!

日历

« 2024-04-28  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 12073
  • 日志数: 19
  • 图片数: 2
  • 建立时间: 2008-10-20
  • 更新时间: 2009-09-24

RSS订阅

Open Toolbar