其神若何,月射寒江。

数据库连接池的思考

上一篇 / 下一篇  2010-07-10 16:05:48 / 个人分类:开发技术

 

下面转一个我自己的文章

 http://liuhanhong.javaeye.com/blog/709771

  对于数据库连接池,一直在考虑为什么不采用单连接呢,所有应用共享该连接来并发
执行sql.因为同一个连接是可以并发的执行sql语句的。但是目前数据库的连接池,一般
是多连接的,每个事务的连接是独占的。csdn上,也有人提过该问题,但是一直没有人
给出答案。今天认真的研究了下,单连接跟多连接的特点。

在多线程并发的访问数据库的时候,我们希望应用能够同时并发的执行sql语句。
如果每次执行sql语句的时候,都去重新建立连接,那么是开销是非常大的,
而且也会导致连接没法进行统一的管理。
方案一 共享单连接
采用所有应用对象共用一个连接,这样大家使用同一个连接并发的执行语句。
1、 执行查询语句
从数据的准确上,我们实验了是没有错误的。
效率上,没有实验。
2、 执行更新语句
各个并发事务中,无法分离各个事务。如果各个事务并发,只会对最新提交的事务有效,
其它事务无效。
解决办法是,把数据库连接作为同步对象,这样可以避免该问题。
但是,相当于每个事务单独的占用该仅有的一个连接了,会带来效率上的问题。

问题一:
String s1="update   ccl_bd_protocoldata set name='1'";
String s2="update   ccl_bd_protocoldata set name='2'";
如果s1,s2同时执行事务,
如果s1,先提交,s2提交的事务就无效了。

问题二:
会出现胀数据
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;


public class RunDb extends Thread {
private Connection conn;
private String sql;
public RunDb(Connection conn,String str)
{
this.conn=conn;
this.sql=str;
}
public void exe(String str)throws Exception{
System.out.println(str);
//执行更新数据
conn.setAutoCommit(false);
Statement stmt=conn.createStatement();
stmt.executeUpdate(str);
conn.commit();
conn.setAutoCommit(true);
        //查询刚刚更新的数据
ResultSet rs=stmt.executeQuery("select name from ccl_bd_protocoldata");
while(rs.next()){
str+="  " +rs.getString("name");
break;
}
System.out.println(str);

}

public void run()  {
// TODO Auto-generated method stub
try {
this.exe(this.sql);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}


public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
Driver driver = (Driver)Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
DriverManager.registerDriver(driver);
Connection con=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "aa", "aaaa");
String s1="update   ccl_bd_protocoldata set name='1'";
String s2="update   ccl_bd_protocoldata set name='2'";
RunDb r1=new RunDb(con,s1);
RunDb r2=new RunDb(con,s2);
r1.start();
r2.start();
}


结果:
update   ccl_bd_protocoldata set name='1'2  
update   ccl_bd_protocoldata set name='2'  2

可以看出,第一条数据,执行的是更新为1,查出来的却是2


  所以共享连接会出现连接的线程安全问题。

方案二 共享多连接
  也就是大家常用的,建立多个连接在池中。在并发执行sql语句,会每个执行请求分配
一个池中的连接。使用完成后,放回池中,其实连接并不断开。
1、 执行查询语句
没有问题
2、 执行更新语句
由于各个执行事务是独立的连接,所以也是互不干扰的,不会出现问题。
   不会因为连接产生线程安全问题,各个事务的连接是独立的。

结论,单单从事务方面来说,使用共享单个数据库连接来说,是会存在不安全问题。
从效率上来说,应该共享单连接数据库连接,没有连接池那么高。因为连接池是同时
执行多个连接。但是连接池耗费的资源应该比较高。


-------------------------2010.7.10

TAG:

 

评分:0

我来说两句

xiaohanjiang

xiaohanjiang

River.liu又名小寒江。曾经从事多年JAVA软件开发工作,这几年一直从事软件测试工作。多年来,一直致力于软件工程、软件开发、软件测试方面的研究。不喜欢自称高手,不愿意自封资深;科学研究讲究的是务实、实践。真理、真知才是硬道理。茫茫海洋,我只希望我的每个理念能游弋于业界之间。我的思想能在你的脑海中徜徉。

日历

« 2024-04-23  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 39800
  • 日志数: 52
  • 建立时间: 2009-12-15
  • 更新时间: 2011-03-14

RSS订阅

Open Toolbar