`
mfcai
  • 浏览: 409154 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

数据库连接池技术的研究与实现

阅读更多
数据库连接池技术,它的原理是,在应用系统运行过程中,同时打开着一定数量的数据库连接,形成数据连接池,需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去,完成某些SQL操作后,系统自动回收,以供其它用户(或进程)调用。现在大多数的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制.不过,比起配置应用服务器提供的数据库连接池,自己写一个数据库连接池更有成就感.

要自己动手写一个连接池,有许多功能上的考虑。
1)连接池的分配与释放
连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。
  对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。
2)连接池的配置与维护
连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。
3)并发问题
  为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为Java语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如:
  public synchronized Connection getConnection()



一个ConnectionPool的实现
以下代码在jdk1.4以上版本编译通过
package test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Vector;

public class ConnectionPool {
 private final Vector pools = new Vector();

 private int clients;

 private final int maxClients=25;

 /**
  * 获取数据库连接 如果当前池中有可用连接,则将池中最后一个返回;若没有,则创建一个新的返回
  */
 public synchronized java.sql.Connection getConnection() {
  java.sql.Connection con = null;
  if (pools.size() > 0) {
   // Pick the first Connection in the Vector
   // to get round-robin usage
   con = (java.sql.Connection) pools.firstElement();
   pools.removeElementAt(0);
   try {
    if (con.isClosed()) {
     System.out
       .println("Removed bad connection from connection pool");
     // Try again recursively
     con = getConnection();
    }
   } catch (SQLException e) {
    System.out
      .println("Removed bad connection from  connection pool");
    // Try again recursively
    con = getConnection();
   }
  } else if (maxClients == 0 || clients < maxClients) {
   con = createConnection();
  }
  if (con != null) {
   clients++;
  }
  return con;
 }

 /*
  * 当对一个连接的请求不能被满足时,等待,直到pool中有空闲Connection
  */
 public synchronized java.sql.Connection getConnection(long timeout) {
  long startTime = new Date().getTime();
  java.sql.Connection con;
  while ((con = getConnection()) == null) {
   try {
    wait(timeout);
   } catch (InterruptedException e) {
   }
   if ((new Date().getTime() - startTime) >= timeout) {
    // Timeout has expired
    return null;
   }
  }
  return con;
 }

 /*
  * 生成一个数据库连接conn
  */
 public static Connection createConnection() {
  Connection conn = null;
  try {
   Class.forName("org.gjt.mm.mysql.Driver").newInstance();
   String url = "jdbc:mysql://localhost:3306/microerp";
   String user = "root";
   String password = "";
   conn = DriverManager.getConnection(url, user, password);
  } catch (InstantiationException e) {
   // TODO自动生成 catch 块
   e.printStackTrace();
  } catch (IllegalAccessException e) {
   // TODO自动生成 catch 块
   e.printStackTrace();
  } catch (ClassNotFoundException e) {
   // TODO自动生成 catch 块
   e.printStackTrace();
  } catch (SQLException e) {
   // TODO自动生成 catch 块
   e.printStackTrace();
  }
  return conn;
 }

 /**
  * 将使用完毕的数据库连接放回池中 若池中连接已经超过阈值,则关闭该连接;否则放回池中下次再使用
  */
 public synchronized void releaseConnection(Connection conn) {
  if (pools.size() >= maxClients)
   try {
    conn.close();
   } catch (SQLException e) {
    // TODO自动生成 catch 块
    e.printStackTrace();
   }
  else {
   pools.add(conn);
   clients--;
   notify();
  }
 }
 
 public synchronized void clear(){
        for(int i=0;i<pools.size();i++){
         Connection conn =(Connection)pools.get(i);
         try {
    conn.close();
   } catch (SQLException e) {
    // TODO自动生成 catch 块
    e.printStackTrace();
   }
        }
        pools.removeAllElements();

}


}

本文欢迎转载,转载时请说明出处.
3
3
分享到:
评论
6 楼 chbest 2008-07-02  
没做过数据源.
但是Connection 本来就是一个接口
然后jdbc得到的Connection和数据源得到的Connection 本来就是不一个实现.
jdbc得到的Connection执行close的时候有可能就是关闭连接,而数据源得到的Connection的close估计只是把Connection返回给数据源而已
5 楼 mfcai 2008-06-30  
这个确实是个难题.不过在实际的开发中,更多的会采用通过CodeReview的管理方式来解决.毕竟,写代码必须遵循一定的规范.team leader的职责之一就是审核代码.
4 楼 pandonix 2008-06-29  
还有一个问题,希望LZ不吝赐教:
假设已经按照LZ回答的方法解决了回收Connection的问题,那么如果在一个多人开发的项目中,组员的水平差别较大,或者说,总有那么些粗心的组员忘记close掉Connection,这些Connection是否一直都被占用?
LZ设计了TimeOut,但似乎是等待有效Connection的时间,而不是在使用的一个连接最长时间。
这样一来,在高并发的情况下,有不少Connection没有被close掉,就很可能造成Connection leak。
当然,可以通过CodeReview的管理方式来解决这个人为问题。而且proxool这样的连接池也没有解决这个问题。
有没有更优雅的解决方案呢?
以下是小弟的拙见:
返回的Connection可以是java.sql.Connection的一个子类,而由其实现finalize方法。在finalize中关闭Connection,并回收给缓冲池。
因为在Connection的使用中,通常都是局部变量,也就是说,该Connection引用会被GC所回收,而回收时会调用finalize方法。
以上方案是借鉴了FileInputStream的实现。
3 楼 mfcai 2008-06-29  
说的很正确.可以在调用Connection.close使用Proxy模式和java反射机制,调用releaseConnection()方法,将数据库链接返回给数据库连接池.
相关代码如下:
public class ConnectionHandler  implements InvocationHandler{
	private Connection conn;

	private ConnectionPool pool;

	public ConnectionHandler(ConnectionPool pool) {
		this.pool = pool;
	}

	/**
	 * 将动态代理绑定到指定Connection
	 * 
	 * @param conn
	 * @return
	 */
	public Connection bind(Connection conn) {
		this.conn = conn;
		Connection proxyConn = (Connection) Proxy.newProxyInstance(conn
				.getClass().getClassLoader(), conn.getClass().getInterfaces(),this);

		return proxyConn;
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
	 *      java.lang.reflect.Method, java.lang.Object[])
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO自动生成方法存根
		Object obj = null;
		if ("close".equals(method.getName())) {
			this.pool.releaseConnection(this.conn);
		} else {
			obj = method.invoke(this.conn, args);
		}

		return obj;
	}
}
2 楼 pandonix 2008-06-29  
对于JDBC的操作,一般都习惯了如下的格式:
try
{
  con = getConnection;
  doDBWork;
}
catch(SQLException ex)
{
}
finally
{
  con.close();
}

LZ的getConnection返回的是java.sql.Connection对象,而当调用Connection.close是直接将connection释放掉了,而并非像c3p,proxool这样的连接池的做法一样,将Connection回收给缓冲池。这样,下次获取Connection还是需要重新创建,是否没有达到缓冲的目的呢?
换句话说,你没法让用户不调用Connection.close,而一旦调用了,就似乎失去了缓冲池的意思。
以上拙见,期待LZ的交流和讨论
1 楼 txxg 2008-06-29  
学习了!

相关推荐

    jsp毕业设计——JSP数据库连接池的研究与实现(源代码+论文).zip

    总的来说,这个毕业设计项目旨在让学生理解和掌握JSP开发中的数据库连接池技术,提升其在实际项目中的应用能力。通过这样的实践,学生不仅能了解数据库连接池的工作机制,还能学习到如何在Java Web应用中有效管理...

    JSP数据库连接池的研究与实现(源代码+论文).zip

    数据库连接池技术可以显著提高应用性能,减少资源消耗,优化数据库操作。本项目主题为“JSP数据库连接池的研究与实现”,其中包含源代码和论文,旨在深入探讨和实践这一技术。 1. 数据库连接池概念: 数据库连接池...

    基于JDBC的数据库连接池技术研究

    ### 基于JDBC的数据库连接池技术研究 #### 一、引言 随着互联网技术的迅猛发展,特别是Web应用的广泛普及,传统的客户端/服务器(C/S)架构已经逐渐被浏览器/服务器(B/S)三层架构所取代。在这种背景下,为了提高...

    基于JSP毕业设计-数据库连接池的研究与实现(源代码+论文).zip

    基于JSP毕业设计-数据库连接池的研究与实现(源代码+论文).zip 在基于JDBC的数据库实际应用开发中,对数据库连接的管理是一个重点也是一个难点,频繁对数据库的连接与关闭操作、多客户对数据库的并发访问,一定程度上...

    JSP数据库连接池的研究与实现(源代码+论文).rar

    《JSP数据库连接池的研究与实现》...总的来说,这个项目是一个很好的实践平台,可以帮助我们深入理解JSP与数据库交互的优化方法,提升Web应用的性能,同时也能提高我们在数据库连接池技术上的理论知识和实际操作能力。

    数据库课程设计,数据库连接池的研究与实现(源代码).zip

    在这个"数据库课程设计,数据库连接池的研究与实现(源代码).zip"压缩包中,包含了关于数据库连接池的完整研究和实践,适合学习者深入理解并实践这个技术。 首先,我们需要了解什么是数据库连接池。数据库连接池是在...

    JSP数据库连接池的研究与实现(源代码+lw).zip

    总结起来,"JSP数据库连接池的研究与实现"是一个涵盖数据库连接池配置、使用和优化的实践项目,对于理解和应用数据库连接池技术,提升JSP应用的性能具有重要的学习价值。通过分析和理解提供的源代码,开发者不仅可以...

    基于java的数据库连接池技术的设计与实现

    ### 基于Java的数据库连接池技术的设计与实现 #### 概述 数据库连接池技术是现代软件开发中的一项关键技术,特别是在Java企业级应用中。它通过预先创建一定数量的数据库连接,并将这些连接组织成一个池,来提高...

    基于JAVA JSP数据库连接池的研究与实现的毕业设计,使用数据库连接池方式能对数据库的连接进行管理和维护,上层应用程序通过数据

    并在学习掌握了实现连接池的关键技术后给出了一个较为高效的连接池管理策略,在这种策略思想的指导下实际开发出一个数据库连接池模块,使得上层应用通过本连接池访问数据库资源变得相对高效和容易,从实际上论证了...

    基于JSP数据库连接池的研究与实现(源代码+论文).zip

    【标题】:“基于JSP数据库连接池的研究与实现(源代码+论文).zip”这个压缩包文件主要包含了一个关于如何在Java服务器页面(JSP)中应用数据库连接池的完整研究项目,包括了源代码和相关论文。这个项目旨在帮助初学...

    数据库连接池的应用与研究

    本文将深入探讨数据库连接池的应用与研究,包括其原理、优点、常见实现以及如何在实际项目中有效地利用它。 首先,我们要理解数据库连接池的基本概念。数据库连接池是一种管理数据库连接的技术,它在应用程序启动时...

    基于JSP数据库连接池的研究与实现毕业设计(源代码+论文)

    【作品名称】:基于JSP数据库连接池的研究与实现【毕业设计】(源代码+论文) 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目...

    JSP数据库连接池的研究与实现(源代码+文档)

    本项目"JSP数据库连接池的研究与实现"着重探讨了如何在JSP应用中有效地管理和利用数据库连接资源,以提高系统效率和响应速度。 首先,了解数据库连接池的概念是必要的。数据库连接池是在应用程序启动时预先建立的一...

    JSP源码JSP数据库连接池的研究与实现(源代码+论文)

    为了提高应用程序的性能和响应时间,通常会采用数据库连接池技术。数据库连接池是一种管理数据库连接的机制,它预先创建一定数量的数据库连接,并将这些连接保存在一个池中。当应用程序需要访问数据库时,可以从连接...

Global site tag (gtag.js) - Google Analytics