数据库连接池的基本原理是在内部对象池中维护一定数量的数据库连接,并对外暴露数据库连接获取和返回方法。如:
外部使用者可通过getConnection 方法获取连接,使用完毕后再通过releaseConnection 方法将连接返回,注意此时连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。
数据库连接池技术带来的优势:
1. 资源重用
由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。
2. 更快的系统响应速度
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
3. 新的资源分配手段
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术,几年钱也许还是个新鲜话题,对于目前的业务系统而言,如果设计中还没有考虑到连接池的应用,那么…….快在设计文档中加上这部分的内容吧。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
4. 统一的连接管理,避免数据库连接泄漏
数据库连接池设计(转载)
一个连接池应用的设计,需要几个关键部分作为支撑,其中最为重要的是DBConnectionPool类和DBConnectionManager类,他们对连接的建立、管理、释放起决定性作用。大体作用列举如下:
1、一个DBConnectionPool类,该类负责从连接池获取(或创建)连接、将连接返回给连接池、空闲连接的超时等待、系统关闭时释放所有资源并关闭所有连接。
2、一个DataSourceProviderServle t类,该类负责通过上下文环境读取配置文件后装载和注册JDBC驱动、数据库名等。
3、一个DBConnectionManager类,该类负责按预先指定的最大连接池数连初始化连接池、创建DBConnectionPool对象provider、当所有的连接客户退出后,关闭全部连接。
4、DBconfig.properties属性文件,该文件中包含了数据库驱动(DriverName)、数据库URL、数据库表空间名(User)、表空间密码(Password)、连接池最大连接数(maxConnections)。
5、即为应用程序对连接池中的连接的调用和释放,应用程序退出后连接池的关闭。
将以上5个部分串连起来,即是本连接池的简单设计流程。首先应用程序向连接池申请连接,就需要通过DBConnectionPool类、DBConnectionManager类对连接池初始化,并且还需要DataSourceProviderServle t类的帮助读取DBconfig.properties文件中的属性,加载和注册JDBC驱动、数据库名等,连接池才能初始化成功。之后通过DBConnectionPool类监视、管理应用程序调用、释放的数据库连接,并通过该类的cp对象将连接使用情况反映在页面上。连接池管理程序得到某个连接,而其他线程就不会得到这个数据库连接了,此线程使用结束后,该线程将连接交还给连接池管理程序,以分配给其他等待连接的请求线程。这里连接池充分利用JAVA的线程同步机理,使当前服务线程处于等待状态,直至有空闲的连接出现。最后当应用程序退出时,通过DBConnectionManager类负责连接池的关闭。
连接池中的管理机制
应用程序开发中“三分技术、七分管理”的思想在连接池的配置中同样得以体现,如何从连接池中取得连接,何时释放连接、如何释放连接等问题还需要为连接池配置更为复杂的管理机制,连接池流程的管理如下图所示,这些属性定义了连接池与其中每个连接的有效状态值。连接池的自我管理,实际上就是通过定时的对每个连接的状态、连接的数量进行判断而进行相应操作。
下面我们以一个名为ConnectionPool的连接池为例来看看连接池的实现。先看看ConnectionPool的基本属性:
m_ConnectionPoolSize:连接池中连接数量下限
m_ConnectionPoolMax:连接池中连接数量上限
m_ConnectionUseCount:一个连接的最大使用次数
m_ConnectionTimeout:一个连接的最长空闲时间
m_MaxConnections = -1:同一时间的最大连接数
m_timer:定时器
这些属性定义了连接池与其中的每个连接的有效状态值。连接池的自我管理,实际上就是通过定时的对每个连接的状态、连接的数量进行判断而进行相应操作。其管理流程如下:
通过上图,我们可以定义出ConnectionPool要完成管理所需要的基本接口:
public class ConnectionPool implements TimerListener{
public boolean initialize() //连接池初始化
public void destroy() //连接池的销毁
public synchronized java.sql.Connection getConnection() //取一个连接
public synchronized void close() //关闭一个连接
private synchronized void removeFromPool() //把一个连接从连接池中删除
private synchronized void fillPool() //维护连接池大小
public synchronized void TimerEvent() //定时器事件处理函数
}
通过这几个接口,已经可以完成连接池的基本管理。在TimeEvent()函数中完成连接池的状态检验工作,fillPool()时连接池至少保持最小连接数。因为我们要保存每一个连接的状态,所以还需要一个数据库连接对象:
class ConnectionObject{
public java.sql.Connection con; public boolean inUse; //是否被使用标志
public long lastAccess; //最近一次开始使用时间
public int useCount; //被使用次数
}
加入了ConnectionObject对象后,在ConnectionPool中操作的应该只是ConnectionObject,而其他进程需要的只是ConnectionObject的con属性,因此我们再加入一个类,作为其他进程获得与返回连接的接口: CLASS Conn{
GetConnection(); //从连接池中取出一个有效连接
CloseConnection(); //返回连接,此时并没有关闭连接,只是放回了连接池
DestroyPool(); //销毁连接池
}