数据库连接池基本原理
数据库连接池——基本原理
数据库连接池——基本原理
1.数据库连接池是什么?
数据库连接池是负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
2.为什么要使用连接池?
数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。 一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下 。
3.连接池的设计思想:
在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池。(换句话说:在一个“池”里放了好多半成品的数据库连接对象)。
由应用程序动态地对池中的连接进行 申请 、 使用 和 释放 。
对于多于连接池中连接数的 并发请求 ,应该在请求 队列中排队 等待。
并且应用程序可以根据池中连接的使用率, 动态增加或减少 池中的连接数。
3.3使用了连接池的好处:
- 连接池技术尽可能多地重用了消耗内存地资源,大大节省了内存,提高了服务器地服务效率,能够支持更多的客户服务。
- 通过使用连接池,将大大提高程序运行效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。
2 传统的连接机制 vs 数据库连接池的运行机制
传统的:
步骤
1. TCP 建立连接 三次握手
2. MySql 认证的 三次握手
3. SQL 的执行
4. MySql 的关闭
5. TCP 的 四次握手 关闭
可以看出:一条SQL语句的执行,其实包含了多次的网络交互。
优点
实现简单
缺点
1. 网络IO较多
2. 数据库的负载较高
3. 响应时间较长及QPS较低 (QPS:每秒查询率)
4. 应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁(java 的垃圾回收方法)
5. 在关闭连接后,会出现大量TIME_WAIT 的TCP状态(在2个MSL之后关闭)
连接池的:
准备好若干的连接 ,数据源完成连接池的管理,(多线程)
步骤:
第一次访问的时候,需要建立连接。 但是之后的访问,均会复用之前创建的连接,直接执行SQL语句。
上下两个灰色部分的每次只执行一次
黄色部分的 执行多次SQL。
优点
1. 减少了网络开销
2. 系统的性能会有一个实质的提升
3. 没了麻烦的TIME_WAIT状态
3.数据库连接池——工作原理
3.1 连接池的建立
一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。
Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。
3.2 连接的管理
连接池管理策略 是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是:
当客户请求数据库连接时,首先查看连接池中是否有空闲连接,如果存在空闲连接,则将连接分配给客户使用;如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,如果没达到就重新创建一个连接给请求的客户;如果达到就按设定的最大等待时间进行等待,如果超出最大等待时间,则抛出异常给客户。
当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。
该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。
3.3 连接池的关闭
当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。
4.注意点
- 并发问题
- 事务处理
- 连接池的分配与释放
- 连接池的配置与维护
1、并发问题
为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即 并发问题 。
这个问题相对比较好解决,因为 各个语言自身提供了对并发管理 的支持像java,c#等等,使用synchronized(java)lock(C#)关键字即可确保线程是同步的。
2、事务处理
我们知道, 事务具有原子性 ,此时要求对数据库的操作符合“ALL-OR-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。
我们知道当2个线程共用一个连接Connection对象,而且各自都有自己的事务要处理时候,对于连接池是一个很头疼的问题,因为即使Connection类提供了相应的事务支持,可是我们仍然不能确定那个数据库操作是对应那个事务的,这是由于我们有2个线程都在进行事务操作而引起的。
为此我们可以使用 每一个事务独占一个连接 来实现,虽然这种方法有点浪费连接池资源但是可以大大降低事务管理的复杂性。
3、连接池的分配与释放
连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。
对于连接的管理可 使用一个List 。即把已经创建的连接都放入List中去统一管理。每当用户请求一个连接时,系统检查这个List中有没有可以分配的连接。如果有就把那个最合适的连接分配给他,如果没有就抛出一个异常给用户。
4、连接池的配置与维护
连接池中到底应该放置多少连接,才能使系统的性能最佳?
系统可采取设置最小连接数(minConnection)和最大连接数(maxConnection)等参数来控制连接池中的连接。比方说, 最小连接数 是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。 最大连接数 是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过软件需求上得到。
如何确保连接池中的最小连接数呢?有 动态 和 静态 两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。
5.数据源(第三方插件)
DBCP
Pool
DBUtils
Loggin
DBCP 数据库连接池属性介绍
#最大连接数量:连接池在同一时间能够分配的最大活动连接的数量,,如果设置为非正数则表示不限制,默认值8
maxActive=15
#最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建,默认值0
minIdle=5
#最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制,默认值8
maxIdle=10
#初始化连接数:连接池启动时创建的初始化连接数量,默认值0
initialSize=5
#连接被泄露时是否打印
logAbandoned=true
#是否自动回收超时连接
removeAbandoned=true
#超时时间(以秒数为单位)
removeAbandonedTimeout=180
# 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常,如果设置为-1表示无限等待,默认值无限
maxWait=3000
#在空闲连接回收器线程运行期间休眠的时间值(以毫秒为单位).
timeBetweenEvictionRunsMillis=10000
#在每次空闲连接回收器线程(如果有)运行时检查的连接数量
numTestsPerEvictionRun=8
#连接在池中保持空闲而不被空闲连接回收器线程
minEvictableIdleTimeMillis=10000
#用来验证从连接池取出的连接
validationQuery=SELECT 1
#指明是否在从池中取出连接前进行检验
testOnBorrow=true
#testOnReturn false 指明是否在归还到池中前进行检验
testOnReturn=true
#设置为true后如果要生效,validationQuery参数必须设置为非空字符串
testWhileIdle
扩展
池(Pool)
池技术 在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销。
- 广义上讲:数据库连接池、线程池、内存池、对象池。
- 优势:可以消除对象创建所带来的延迟,从而提高系统的性能。
对象池
可以看成保存对象的容器,在进程初始化时创建一定数量的对象。需要时直接从池中取出一个空闲对象,用完后并不直接释放掉对象,而是再放到对象池中以方便下一次对象请求可以直接复用。(其他几种池的设计思想也是如此.)
数据库连接池(connection pool)的原理
要了解 Java连接池 我们先要了解 数据库连接池 (connection pool)的原理,Java连接池正是数据库连接池在Java上的应用。——我们知道,对于共享资源,有一个很著名的设计模式: 资源池(Resource Pool) 。
该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个**“缓冲池”**。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。
常见的连接池
C3P0 :
(主页:http://sourceforge.net/projects/c3p0/)
是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
BoneCP
(主页:http://jolbox.com/)
是一个开源的快速的 JDBC 连接池。BoneCP很小,只有四十几K(运行时需要log4j和Google Collections的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。另外个人觉得 BoneCP 有个缺点是,JDBC驱动的加载是 在连接池之外 的,这样在一些应用服务器的 配置上就不够灵活 。当然,体积小并不是 BoneCP 优秀的原因,BoneCP 到底有什么突出的地方呢,请看看性能测试报告。
DBCP
(主页:http://commons.apache.org/dbcp/)
是一个依赖Jakarta commons-pool对象池机制的数据库连接池, Tomcat的数据源 使用的就是DBCP。目前 DBCP 有两个版本分别是 1.3 和 1.4。1.3 版本对应的是 JDK 1.4-1.5 和 JDBC 3,而1.4 版本对应 JDK 1.6 和 JDBC 4。因此在选择版本的时候要看看你用的是什么 JDK 版本 了,功能上倒是没有什么区别。
Proxool
是一个Java SQL Driver驱动程序,提供了对你选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中。完全可配置。快速,成熟,健壮。可以透明地为你现存的JDBC驱动程序增加连接池功能。
Java中常用的数据库连接池有:
DBCP 、C3P0、BoneCP、Proxool、DDConnectionBroker、DBPool、XAPool、Primrose、SmartPool、MiniConnectionPoolManager及Druid等。
Java开源数据连接池:
Hibernate常用三种连接池的配置:
几种常用java连接池: