用了这么久的数据库连接池,你知道原理吗?( 二 )


三、连接池还要考虑更多的问题
【用了这么久的数据库连接池,你知道原理吗?】1、并发问题
为了使连接管理服务具有最大的通用性 , 必须考虑多线程环境 , 即并发问题 。这个问题相对比较好解决 , 因为java语言自身提供了对并发管理的支持 , 使用synchronized关键字即可确保线程是同步的 。使用方法为直接在类方法前面加上synchronized关键字 , 如:
publicsynchronized connection getconnection()2、多数据库服务器和多用户
对于大型的企业级应用 , 常常需要同时连接不同的数据库(如连接oracle和sybase) 。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类 , 在连接池管理类的唯一实例被创建时读取一个资源文件 , 其中资源文件中存放着多个数据库的url地址等信息 。根据资源文件提供的信息 , 创建多个连接池类的实例 , 每一个实例都是一个特定数据库的连接池 。连接池管理类实例为每个连接池实例取一个名字 , 通过不同的名字来管理不同的连接池 。
对于同一个数据库有多个用户使用不同的名称和密码访问的情况 , 也可以通过资源文件处理 , 即在资源文件中设置多个具有相同url地址 , 但具有不同用户名和密码的数据库连接信息 。
3、事务处理
我们知道 , 事务具有原子性 , 此时要求对数据库的操作符合“all-all-nothing”原则即对于一组sql语句要么全做 , 要么全不做 。
在java语言中 , connection类本身提供了对事务的支持 , 可以通过设置connection的autocommit属性为false 然后显式的调用commit或rollback方法来实现 。但要高效的进行connection复用 , 就必须提供相应的事务支持机制 。可采用每一个事务独占一个连接来实现 , 这种方法可以大大降低事务管理的复杂性 。
4、连接池的分配与释放
连接池的分配与释放 , 对系统的性能有很大的影响 。合理的分配与释放 , 可以提高连接的复用度 , 从而降低建立新连接的开销 , 同时还可以加快用户的访问速度 。
对于连接的管理可使用空闲池 。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中 。每当用户请求一个连接时 , 系统首先检查空闲池内有没有空闲连接 。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断 , 如果可用就分配给用户 , 如不可用就把这个连接从空闲池删掉 , 重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxconn)如果没有达到 , 就新建一个连接 , 如果已经达到 , 就等待一定的时间(timeout) 。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户 , 如果等待时间超过预定时间timeout 则返回空值(null) 。系统对已经分配出去正在使用的连接只做计数 , 当使用完后再返还给空闲池 。对于空闲连接的状态 , 可开辟专门的线程定时检测 , 这样会花费一定的系统开销 , 但可以保证较快的响应速度 。也可采取不开辟专门线程 , 只是在分配前检测的方法 。
5、连接池的配置与维护
连接池中到底应该放置多少连接 , 才能使系统的性能最佳?系统可采取设置最小连接数(minconn)和最大连接数(maxconn)来控制连接池中的连接 。最小连接数是系统启动时连接池所创建的连接数 。如果创建过多 , 则系统启动就慢 , 但创建后系统的响应速度会很快;如果创建过少 , 则系统启动的很快 , 响应起来却慢 。这样 , 可以在开发时 , 设置较小的最小连接数 , 开发起来会快 , 而在系统实际使用时设置较大的 , 因为这样对访问客户来说速度会快些 。最大连接数是连接池中允许连接的最大数目 , 具体设置多少 , 要看系统的访问量 , 可通过反复测试 , 找到最佳点 。
如何确保连接池中的最小连接数呢?有动态和静态两种策略 。动态即每隔一定时间就对连接池进行检测 , 如果发现连接数量小于最小连接数 , 则补充相应数量的新连接以保证连接池的正常运转 。静态是发现空闲连接不够时再去检查 。


推荐阅读