- 浏览: 681867 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (198)
- 编程经验 (12)
- 移动端 (2)
- linux (1)
- 基础理论 (10)
- 开发工具 (8)
- 开发语言_java (21)
- 开源框架_Axis2 (8)
- GIS开发_OpenLayers (9)
- GIS开发_ArcGIS (6)
- GIS开发_googleAPI (4)
- GIS开发_AO (2)
- Web前端_Javascript (7)
- Web前端_CSSDIV (2)
- Web前端_WebGL (5)
- Web前端_HTML5 (1)
- 数据库 (17)
- 项目管理 (6)
- REST服务_Restlet (0)
- REST服务_RestEasy (5)
- 连接池 (6)
- 框架组合_SSI (7)
- 框架组合_SSH (37)
- 异常处理 (10)
- 测试 (1)
- ASP/ASP.NET (3)
- 我所遇到的JavaScript (1)
- cas (1)
- CI (1)
- nginx (1)
- 大数据 (1)
- maven (1)
- 机器学习 (0)
最新评论
-
章元o:
正解,问题解决了,要换tomcat的
webservice开发时项目启动过程中出现版本问题 -
dcloud:
大师,按照你的指点进行初始化工作,但是在connection. ...
AO连接sde出现java.lang.UnsatisfiedLinkError: no ntvauth in java.library.path -
yiran0314:
您好 关于这个问题能描述得更详细一点吗?
CXF异常处理 -
tianhandigeng:
找了半个小时了也没小号到m2e最新的地址,既然这个都让你找得这 ...
Myeclipse8.6安装Maven插件------ -
wxb880114:
这个发的比较早了,现在在myeclipse中有自带的,ecli ...
Myeclipse8.6安装Maven插件------
基于JDBC的数据库连接池高效管理策略
发布时间:2007.04.02 01:49 来源:cnjsp 作者:孙鸣
在基于JDBC的数据库应用开发中,数据库连接的管理是一个难点,因为它是决定该应用性能的一个重要因素。本文在对数据库连接进行透彻分析的基础上,提出并实现了一个高效的连接管理策略,使得开发高性能的数据库应用变得相对容易。特别是,对于连接管理中的两个难点:事务和多线程问题进行了深入的剖析,并给出了一个基于设计模式的解决方案。
介绍
在使用Java语言进行和数据库有关的的应用开发中,一般都使用JDBC来进行和数据库的交互,其中有一个关键的概念就是Connection(连接),它在Java中是一个类,代表了一个通道。通过它,使用数据的应用就可以从数据库访问数据了。
对于一个简单的数据库应用,由于对于数据库的访问不是很频繁。这时可以简单地在需要访问数据库时,就新创建一个连接,用完后就关闭它,这样做也不会带来什么明显的性能上的开销。但是对于一个复杂的数据库应用,情况就完全不同了。频繁的建立、关闭连接,会极大的减低系统的性能,因为对于连接的使用成了系统性能的瓶颈。
本文给出的方法可以有效的解决这个问题。在本方法中提出了一个合理、有效的连接管理策略,避免了对于连接的随意、无规则的使用。该策略的核心思想是:连接复用。通过建立一个数据库连接池以及一套连接使用管理策略,使得一个数据库连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销。另外,由于对JDBC中的原始连接进行了封装,从而方便了数据库应用对于连接的使用(特别是对于事务处理),提高了开发效率,也正是因为这个封装层的存在,隔离了应用的本身的处理逻辑和具体数据库访问逻辑,使应用本身的复用成为可能。
问题产生
我参与的项目是开发一个网管系统,不可避免的要和数据库打交道。刚开始时,由于对于数据库的访问不是很频繁,对于数据库连接的使用就是简单的需要时就建立,用完就关闭的策略,这很符合XP(eXtreme Programming)的口号:"Do the Simplest Thing that Could Possibly Work"。确实,开始时工作的很好。随着项目的进展,对于数据库的访问开始变的频繁,问题就暴露出来了,原先的通过简单地获取和关闭数据库连接的方法将很大的影响系统的性能,这种影响是由于数据库资源管理器进程频繁的创建和摧毁那些连接对象而引起的。
此时,就有必要对数据库访问方法进行重构(refactoring),因为我们确实需要进行改进,来提高系统的性能。
解决方案
可以看出,问题的根源就是由于对于连接资源的低效管理造成的。对于共享资源,有一个很著名的设计模式:资源池。该模式正是为了解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域,就是建立一个数据库连接池,提供一套高效的连接分配、使用策略,最终目标是实现连接的高效、安全的复用。
3.1、建立连接池
第一步,就是要建立一个静态的连接池,所谓静态是指,池中的连接是在系统初始化时就分配好的,并且不能够随意关闭的。Java中给我们提供很多容器类可以方便的用来构建连接池,如:Vector、Stack等。在系统初始化时,根据配置创建连接并放置在连接池中,以后所使用的连接都是从该连接池中获取的,这样就可以避免连接随意建立、关闭造成的开销(当然,我们没有办法避免Java的Garbage Collection带来的开销)。
3.2、分配、释放策略
有了这个连接池,下面我们就可以提供一套自定义的分配、释放策略。
当客户请求数据库连接时,首先看连接池中是否有空闲连接,这里的空闲是指,目前没有分配出去的连接。如果存在空闲连接则把连接分配给客户,并作相应处理,具体处理策略,在关键议题中会详述,主要的处理策略就是标记该连接为已分配。若连接池中没有空闲连接,就在已经分配出去的连接中,寻找一个合适的连接给客户(选择策略会在关键议题中详述),此时该连接在多个客户间复用。
当客户释放数据库连接时,可以根据该连接是否被复用,进行不同的处理。如果连接没有使用者,就放入到连接池中,而不是被关闭。
可以看出正是这套策略保证了数据库连接的有效复用。
3.3、配置策略
数据库连接池中到底要放置多少个连接,连接耗尽后该如何处理呢?这时一个配置策略。一般的配置策略是,开始时,根据具体的应用需求,给出一个初始的连接池中连接的数目以及一个连接池可以扩张到的最大连接数目。本方案就是按照这种策略实现的。
关键议题
本节将对上述解决方案中的关键细节进行详述,正是这些关键的策略保证了数据库连接复用的高效和安全。
4.1、引用记数
3.2节中的分配、释放策略对于有效复用连接非常重要,我们采用的方法也是采用了一个很有名的设计模式:Reference Counting(引用记数)。该模式在复用资源方面用的非常广泛,我们把该方法运用到对于连接的分配释放上。每一个数据库连接,保留一个引用记数,用来记录该连接的使用者的个数。具体的实现上,我们采用了两极连接池,空闲池和使用池。空闲池中存放目前还没有分配出去被使用的连接,一旦一个连接被分配出去,那么就会放入到使用池中,并且增加引用记数。
这样做有一个很大的好处,使得我们可以高效的使用连接,因为一旦空闲池中的连接被全部分配出去,我们就可以根据相应的策略从使用池中挑选出一个已经正在使用的连接用来复用,而不是随意拿出一个连接去复用。策略可以根据需要去选择,我们采用的策略比较简单:复用引用记数最小的连接。Java的面向对象特性,使得我们可以灵活的选择不同的策略(提供一个不同策略共用的抽象接口,各个具体的策略都实现这个接口,这样对于策略的处理逻辑就和策略的实现逻辑分离)。
4.2、事务处理
前面谈到的都是关于使用数据库连接进行普通的数据库访问。对于事务处理,情况就变得比较复杂。因为事务本身要求原子性的保证,此时就要求对于数据库的操作符合"All-All-Nothing"原则,即要么全部完成,要么什么都不做。如果简单的采用上述的连接复用的策略,就会发生问题,因为没有办法控制属于同一个事务的多个数据库操作方法的动作,可能这些数据库操作是在多个连接上进行的,并且这些连接可能被其他非事务方法复用。
Connection本身具有提供了对于事务的支持,可以通过设置Connection的AutoCommit属性为false,显式的调用commit或者rollback方法来实现。但是要安全、高效的进行Connection进行复用,就必须提供相应的事务支持机制。我们采用的方法是:采用显式的事务支撑方法,每一个事务独占一个连接。这种方法可以大大降低对于事务处理的复杂性(如果事务不独占一条连接,那么要保证事务的原子性并且又不妨碍复用该连接的其他和该事务无关的操作,基本上不可能,除非Connection类是你开发的),并且又不会妨碍连接的复用,因为隶属于该事务的所有数据库操作都是通过这一个连接完成的,并且事务方法又复用了其他一些数据库方法。
在我们的连接管理服务提供了显式的事务开始、结束(commit或者rollback)声明,以及一个事务注册表,用于登记事务发起者和事务使用的连接的对应关系,通过该表,使用事务的部分和我们的连接管理部分就隔离开,因为该表是在运行时根据实际的调用情况,动态生成的。事务使用的连接在该事务运行中不能被复用。
当使用者需要使用事务方法时,首先调用连接管理服务提供的beginTrans方法,该方法主要处理流程如下(伪码描述):
public void beginTrans( ) {
…
conn = getIdleConnectionFromPoll( );
userId = getUserId( );
registerTrans(userId, conn);
…
}
在我们的实现中,用户标识是通过使用者所在的线程来标识的。后面的所有对于数据库的访问都是通过查找该注册表,使用已经分配的连接来完成的。当事务结束时,从注册表中删除相应表项。
对于嵌套的事务如何处理呢?我们采用的方法仍为引用记数,不过这里的引用记数是指的"嵌套层次",具体的细节,不再赘述。
4.3、封装
从上面的论述可以看出,普通的数据库方法和事务方法对于连接的使用(分配、释放)是不同的,为了便于使用,对外提供一致的操作接口,我们对连接进行了封装:即普通连接和事务连接。在此,我们利用了Java中的强大的面向对象特性:多态。普通连接和事务连接均实现了一个DbConnection接口,对于接口中定义的方法,分别根据自己的特点作了不同的实现,这样在对于连接的处理上就非常的一致了。
4.4、并发问题
为了是我们的连接管理服务有更大的通用性,就必须要考虑到多线程环境,即并发问题。在一个多线程的环境下,我们必须要保证连接管理自身数据的一致性和连接内部数据是一致性,还好Java提供对这方面的很好的支持(synchronized关键字),这样我们就很容易使连接管理成为线程安全的。
5、结论
本文给出了一个基本的连接管理框架,在其中使用了一些广泛使用的设计模式(资源池,引用记数等),使得高效、安全的复用数据库连接成为可能。当然,还有一些问题没有考虑到,比如:没有实现对不同种类的数据库的联合管理;没有提供定时检测机制,查询连接的状态等。另外在连接管理的使用包装上比起一些商用的系统还显粗糙,但是底层的基理是一致的,所以通过本文相信对于这些商用的产品中的相关功能会有更好的理解。
参考文献
《Thinking in Java》Bruce Eckel
《Real-Time Design Patterns》 Bruce Powel Dougladd
发表评论
-
浅析Static用法解析java语言
2013-05-08 10:32 813在类中定义的数据成为 ... -
httpclient报异常
2013-03-17 21:14 3349Exception in thread "main& ... -
(转载)java synchronized详解
2013-01-25 10:44 772java synchronized详解 记下来,很重要。 ... -
JDBC Connection接口实现ResultSet的方法
2013-01-24 15:27 1148JDBC Connection接口实现Resu ... -
关于一个大型WEB系统架构设计和技术选型的讨论摘录
2013-01-23 09:06 1004关于一个大型WEB系统架 ... -
技术选型(转)
2013-01-22 21:41 821博客分类: Java SpringHi ... -
HTTP Status 405 - HTTP method GET is not supported by this URL
2012-11-30 13:25 1364出现错误的原因: 1,继承HttpServlet的Ser ... -
JVM内存资源耗尽,有解决方案吗?
2012-09-24 09:09 972去了趟sun,知道为什么了,heap,stack都有大小限制. ... -
转载 :网站并发测试工具
2012-09-21 09:33 950转载 :网站并发测试工 ... -
获取客户端Ip地址网上方案总结
2012-09-09 11:03 1095客户端: <script language=" ... -
对象与JSON之间的转换
2012-09-04 10:13 944JSON-lib这个Java类包用于把bean,map和XML ... -
调用JSONArray.fromObject(stss)出现java.lang.reflect.InvocationTargetException错误
2012-09-03 12:01 3731调用JSONArray.fromObject(stss)出现j ... -
How Tomcat Work——Tomcat 的默认连接器
2012-08-28 07:48 781注意: 本章中提及的“ ... -
Socket用法详解-----转载
2012-08-24 09:22 1614Socket用法详解 原文:ht ... -
数据结构与算法——数组实现Stack代码
2012-08-17 20:33 903package com.part02; publ ... -
数据结构与算法——简单排序
2012-08-14 21:13 849public class Sort { //存值 ... -
EL表达式取值
2012-07-23 16:55 1444EL表达式取值 1.EL表达式的语法格式很简单: 以前 ... -
Java基础学习------Vector类
2012-07-16 09:47 970一、定义 Vector 类可 ... -
Java基础学习------字符串、String类、StringBuffer类、StringBuilder类总结
2012-07-14 15:09 947一、定义: 字符串是字符的序列、它可以包含字母、数字和其 ... -
java字符串与整数之间的互相转换
2012-07-12 09:32 1639java字符串与整数之间的互相转换 1、如何将字符串S ...
相关推荐
Java JDBC 数据库连接池总结 Java 语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁。在 Web 应用开发的早期,主要使用的技术是 CGIASPPHP 等。之后,Sun 公司推出了基于 Java 语言的 ...
《基于JDBC的数据库连接池技术研究与应用》 在当今互联网时代,Web应用程序的开发已经从传统的桌面应用转向了基于B/S架构的模式。Java的Servlet+JSP+JavaBean技术因其跨平台、安全、高效和可移植的特性,成为了开发...
JDBC数据库连接池总结 一、JDBC数据库连接池概述 在基于B/S架构的三层开发模式中,Java应用程序访问数据库的基本原理是通过JDBC(Java DataBase Connection)技术。JDBC是一种“开放”的方案,为数据库应用开发...
本篇文章将深入探讨Java JDBC数据库连接池的工作原理及其重要性。 ### 数据库连接池的工作原理 1. **初始化**: 应用程序启动时,连接池会预先创建一定数量的数据库连接并保存在池中。这些连接被称为“空闲连接”。...
并在学习掌握了实现连接池的关键技术后给出了一个较为高效的连接池管理策略,在这种策略思想的指导下实际开发出一个数据库连接池模块,使得上层应用通过本连接池访问数据库资源变得相对高效和容易,从实际上论证了...
使用数据库连接池方式能对数据库的连接进行管理和维护,上层应用程序通过数据库连接池使用数据库资源能提升系统性能,充分利用系统资源。文章通过介绍、分析数据库连接池工作的基本原理,了解目前流行的WEB服务器在...
本文主要探讨了基于JDBC的数据库连接池的理论基础、实际应用及其优化策略。 首先,数据库连接池的基本原理在于预创建一定数量的数据库连接,存储在一个池中供应用程序使用。当一个请求需要与数据库建立连接时,不再...
并在学习掌握了实现连接池的关键技术后给出了一个较为高效的连接池管理策略,在这种策略思想的指导下实际开发出一个数据库连接池模块,使得上层应用通过本连接池访问数据库资源变得相对高效和容易,从实际上论证了...
Java数据库连接池(JDBC Connection Pool)是Java应用程序与数据库交互的重要工具,它解决了在Web应用程序中频繁创建和关闭数据库连接导致的资源浪费和性能瓶颈问题。随着互联网技术的发展,高并发、高性能的系统...
数据库连接池是数据库管理中的重要组成部分,主要用于优化数据库的连接创建、分配和释放,从而提高系统性能和资源利用率。在Java开发中,常见的数据库连接池实现有三种:C3P0、DBCP和HikariCP。下面将详细介绍这三种...
### 数据库连接池原理 #### 一、背景与价值 ##### 1.1 背景 在现代软件开发中,应用程序与数据库之间的交互是非常常见的。为了提高这种交互的效率和减少资源消耗,通常会使用数据库连接池技术。连接池位于应用...
并在学习掌握了实现连接池的关键技术后给出了一个较为高效的连接池管理策略,在这种策略思想的指导下实际开发出一个数据库连接池模块,使得上层应用通过本连接池访问数据库资源变得相对高效和容易,从实际上论证了...
并在学习掌握了实现连接池的关键技术后给出了一个较为高效的连接池管理策略,在这种策略思想的指导下实际开发出一个数据库连接池模块,使得上层应用通过本连接池访问数据库资源变得相对高效和容易,从实际上论证了...
数据库连接池是应用程序管理和维护数据库连接的一种高效策略,它的核心思想是减少创建和销毁数据库连接的开销。在没有连接池的情况下,每次需要与数据库交互时,程序都会创建一个新的连接,执行完毕后再关闭该连接。...
DBCP(Database Connection Pool)是Apache软件基金会的一个开源项目,全称为Apache Commons DBCP,它是一个基于Java的数据库连接池实现。在Java应用程序中,DBCP被广泛用于管理数据库连接,以提高性能和资源利用率...
### 基于Java的数据库连接池技术在即时通信系统中的应用 #### 一、引言 随着互联网技术的发展,...未来的研究还可以进一步探索如何更好地利用多线程技术以及更高级的连接管理策略来进一步优化数据库连接池的表现。
在Java中,实现数据库连接池的目的是为了高效地管理和复用数据库连接,避免频繁创建和销毁连接带来的性能开销。本文将深入探讨如何用Java编写一个简单的数据库连接池,并分析其在并发访问中的应用。 首先,数据库...