多个线程共享一个connection的问题

lzheng2001 2007-11-28 12:04:45
多个线程(客队端)共享一个connection的问题. 如果其中一个事务执行了commit语句,其它事务修改的数据会不会也同时被commit?
如果会,请问有没有方法可以让每个线程的事务独立,相互commit但不影响? 我知道不同的数据库处理可能不同,大家可以分别讨论不同数据库.

这里只讨论多线程共享一个connection的问题。 如果为每次个线程(客队端)new 一个connection这个方法我知道,我只想讨论共享一个connection的可行性. 因为共享一个connection性能会更高.
...全文
994 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
obullxl 2011-09-03
  • 打赏
  • 举报
回复
一直DBCP和Spring的事务管理。
lifelovers 2008-12-22
  • 打赏
  • 举报
回复
能不能提供个VC的?我的这个程序出问题,帮帮忙看下~
BOOL CPatientLogin::OnInitDialog()
{
CDialog::OnInitDialog();

CString ListID;

m_fy.AddString("1元");
m_fy.AddString("2元");
m_fy.AddString("3元");

_ConnectionPtr m_pConnection;
_CommandPtr m_pCommand;
_RecordsetPtr m_pRecordset;

m_pConnection.CreateInstance(_uuidof(Connection));
m_pRecordset.CreateInstance(_uuidof(Recordset));
m_pCommand.CreateInstance("ADODB.COMMAND");
try{
_bstr_t strConnect = "driver={SQL Server};server=CHINESE-20171AC\\SQLEXPRESS;DATABASE=HISdata;UID=bbs;PWD=bbs111;";
m_pConnection->Open(strConnect,"","",-1);
CString strSQL="select * from Department";
BSTR bstrSQL=strSQL.AllocSysString();
m_pRecordset->Open(bstrSQL,(IDispatch *)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText);
_variant_t varValue;
varValue = m_pRecordset->Fields->GetItem("DepartmentID")->Value;
if(varValue.vt!=VT_NULL){
while(!m_pRecordset->adoEOF)
{
m_ks.AddString((char *)_bstr_t(varValue = m_pRecordset->Fields->GetItem("DepartmentID")->Value));
m_pRecordset->MoveNext();
}
}
strSQL="select * from PatientLogin";
bstrSQL=strSQL.AllocSysString();
m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText); varValue=m_pRecordset->Fields->GetItem("CaseID")->Value;
if(varValue.vt!=VT_NULL){
m_pRecordset->MoveLast();
ListID=(char *)_bstr_t(varValue = m_pRecordset->Fields->GetItem("CaseID")->Value);
int m=atoi(ListID);
m++;
m_mz.SetWindowText(_bstr_t(m));
}
}
catch(_com_error e)
{
AfxMessageBox(e.Description());
}
m_pRecordset->Close();
return TRUE;
}
出错是从颜色标记处开始的
lzheng2001 2007-12-04
  • 打赏
  • 举报
回复
我提出共享一个connection的想法,是因为我知道sql server 在一个connection 中 可以分成n个transaction, 而commit的时候,也是可以针对某个transaction来提交, 从这个理论来看, 多个用户使用同一个connection 但又相互不影响大家保存数据,这好象是可能的, 但我没具体实践过. 或许不是所有的数据库都支持.
SINCE1978 2007-11-29
  • 打赏
  • 举报
回复
利用ThreadLocal管理数据源是hibernate采用的方式。
j2ee对于每一个请求创建一个线程为其服务,ThreadLocal就是为每个线程保存资源的工具。
链接con共享肯定是不可能的,那样事务根本没法管理,更别说复杂的事务管理了。
连接池属于链接复用而不是链接共享,con链接在同一时刻是为一个客户服务的直到客户归还了该链接。
lip009 2007-11-28
  • 打赏
  • 举报
回复
显然共享是不可取的!
简单介绍连接池机制:
1.项目启动时创建好初始数目的数据库连接,初始为空闲状态!这部分连接将永远不会断开,直到你的应用程序退出运行!
2.当某个类要使用连接时,到连接池中随机找寻一个空闲状态的连接给此类使用,此时修改该连接状态为使用,此状态告诉其他类将不能再使用该连接,直到该连接重新被置成空闲状态!
3.当该类使用完该连接以后调用close方法将该连接归还连接池,将状态修改为空闲状态!此处的close方法并不是真正的关闭连接,而是将连接放回到连接池中.
4.当连接池中所有的连接都被使用,而又有新的使用连接请求时,那么连接池会自动去创建一个新的连接供使用,该新连接使用完后不会被断开,将永久留在连接池中.此时连接池中连接的数目将增加一个.
5.直到连接池中的连接数目达到配置的最大数目,并且所有的连接都在被使用时,再有新的要使用连接的请求才会处于等待状态.但一般情况下该情况几乎不会发生.因为所有的地方同一时刻使用连接的并发几率很小!所以根据自己项目中并发情况来设置连接池中连接的数目.
6.连接池里的连接在使用完后,必须调用相应的close方法将连接归还到连接池当中,这样才能保证连接池正常使用.否则长时间不归还连接会导致连接池无可用连接,从而导致应用无法操作.
qybao 2007-11-28
  • 打赏
  • 举报
回复
多个线程(客队端)共享一个connection的问题. 如果其中一个事务执行了commit语句,其它事务修改的数据会不会也同时被commit?
--------------


如果会,请问有没有方法可以让每个线程的事务独立,相互commit但不影响? 我知道不同的数据库处理可能不同,大家可以分别讨论不同数据库.
--------------
一个客户端一个connection,如果担心connection太多,就用数据库连结池,取不到数据库连结的客户端会等待

这里只讨论多线程共享一个connection的问题。 如果为每次个线程(客队端)new 一个connection这个方法我知道,我只想讨论共享一个connection的可行性. 因为共享一个connection性能会更高.
--------------
不可行,每个客户端有相对独立的事务,所以不应该互相干扰
lip009 2007-11-28
  • 打赏
  • 举报
回复
提高性能最好的方法是采用连接池管理连接的方式,而非共享!共享要大家互不影响,只能加线程安全处理!这样性能更慢!
seaforce 2007-11-28
  • 打赏
  • 举报
回复
你在线程里提交不行吗?
lip009 2007-11-28
  • 打赏
  • 举报
回复
6.在业务中使用该数据库连接

/**
* 根据用户ID查询用户信息
* @param doi 用户信息对象父接口,包含有用户ID参数
* @return 返回查询结果对象父接口引用
*/
public DataObjectIF findOne(DataObjectIF doi) {
java.sql.Connection conn = null;
java.sql.ResultSet rs = null;
java.sql.PreparedStatement ps = null;

UserInfoData uid = (UserInfoData) doi;
UserInfoData result = new UserInfoData();
String sql = "select * from user_info where id=?";
conn = DBConnectionManager.getInstance().getConnection();
try {
ps = conn.prepareStatement(sql);
ps.setLong(1, uid.getId());
rs = ps.executeQuery();
if (rs.next()) {
result.setId(rs.getLong("id"));
result.setUsername(rs.getString("username"));
result.setPassword(rs.getString("password"));
}
}
catch (SQLException ex) {
ex.printStackTrace();
}
finally {
try {
DBConnectionManager.getInstance().closeAll(conn, null, ps, null, rs);
}
catch (Exception ex1) {
ex1.printStackTrace();
}
}
return result;
}
lip009 2007-11-28
  • 打赏
  • 举报
回复
3.数据库连接管理类

/**
* Author:BluesLee
* CreateDate:2006-06-12 22:51:00
* Modifier:BluesLee
* ModifyDate:2006-06-12 22:51:00
* Version:1.0
* Copyright\u00A92006 xxxx 沪ICP备06××××××号
* All right reserved.
*/
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.apache.log4j.Logger;
import java.sql.DriverManager;
/**
* 本类是数据库连接的管理类,因此在整个系统中没有必要出现多个,一个就够用了
* 因此,决定在此类上使用单态设计模式,只提供本类的一个实例出去。
* 在此我是用单态的饿汉模式进行使用
*/
public class DBConnectionManager {
private static Logger logger=Logger.getLogger(DBConnectionManager.class.getName());
/**
* 本静态变量用来存放本系统启动时由Struts生成的连接池的数据源
*/
private static DataSource datasource;
/**
* 由于本类使用单态设计模式,因此不允许在使用中通过New进行实例化,那么本类就要提供一个
* 此类的实例供外界使用,这就是供外界使用的实例
*/
private static DBConnectionManager dbConManager=new DBConnectionManager();
private DBConnectionManager(){}
/**
* 此静态方法用来向类的静态变量赋值,用来在系统中使用
* @param mydatasource 传入的struts生成的数据源
*/
public static void setDatasource(DataSource mydatasource) {
logger.info("设置数据源");
if(datasource==null){
datasource = mydatasource;
}
}
/**
* 由于本类使用单态模式,不允许其他的类使用New进行创建实例
* 因此在这里提供一个共有的静态方法来向外界提供自己的一个实例。
* @return 返回本类的唯一实例
*/
public static DBConnectionManager getInstance() {
logger.info("获得数据库连接管理类的实例");
return dbConManager;
}
/**
* 此方法提供一个可用的数据库连接,从连接池中取得可用连接
* @return 可用的数据库连接
*/
public Connection getConnection() {
Connection conn = null;
try {
logger.info("从连接池中获得空闲的数据库连接");
logger.info(datasource);
conn = datasource.getConnection();
logger.info("拿到连接---------");
return conn;
}
catch (SQLException ex) {
ex.printStackTrace();
}
return null;
}
/**
* 这是一个用来关闭所有的数据库连接相关的打开对象的方法,这样作的好处是不用在每一次调用了sql之后
* 要写一大串的关闭操作。
* @param conn 将要关闭的数据库连接
* @param st 将要关闭的数据库操作对象
* @param pst 将要关闭的预处理数据库操作对象
* @param cst 将要关闭的数据库存储过程调用对象
* @param rst 将要关闭的数据库记录集对象
* @throws java.lang.Exception 有可能要抛出的异常
*/
public void closeAll(Connection conn,Statement st,PreparedStatement pst,CallableStatement cst,ResultSet rst)
throws Exception{
if(rst!=null){
rst.close();
}
if(st!=null){
st.close();
}
if(pst!=null){
pst.close();
}
if(cst!=null){
cst.close();
}
if(conn!=null){
conn.close();
}
logger.info("==========>关闭连接成功!");
}
}

4.在servlet里获取数据源

public class MyServlet extends HttpServlet {

public MyServlet() {
super();
}

public void init() throws ServletException {
/**得到数据源*/
try {
Context initCtx = new InitialContext();
DataSource datasource = (DataSource) initCtx.lookup(
"java:comp/env/jdbc/MyDBA");
DBConnectionManager.setDatasource(datasource);
logger.info("DataSourcePlugIn已经初始化完成...");
}
catch (NamingException ex) {
ex.printStackTrace();
}
}
public void destroy() {
super.destroy();
}

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}

5.在web.xml里配置该servlet在项目启动的时候加载

<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
lip009 2007-11-28
  • 打赏
  • 举报
回复
1.在Tomcat目录下conf/server.xml里配置你的web工程,同时配置连接池

<Context docBase="myweb" path="/myweb" reloadable="true">
<ResourceParams name="jdbc/DBPool">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>oracle.jdbc.driver.OracleDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:oracle:thin:@10.1.1.101:1521:orcl</value>
</parameter>
<parameter>
<name>username</name>
<value>oracle</value>
</parameter>
<parameter>
<name>password</name>
<value>oracle</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>10</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>10</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>-1</value>
</parameter>
</ResourceParams>

</Context>

2.在你的web工程里的web.xml配置JNDI
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/DBPool</res-ref-name>注意这里的名字和上边连接池的名字要一致
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
sharpyuce 2007-11-28
  • 打赏
  • 举报
回复

看到这个问题,我想到一个新的方法,不知道能不能实现:
使用ThreadLocal来实现:
写一个工具类来得到Connection:
public class UtilConnection{

private static ThreadLocal local = new TreadLocal();
static {
try{
class.forName("oracle.jdbc.driver.DriverOracle");
}catch(....){
}
}

public static Connection getCurrentConnection(){
Connection con =(Connection) local.get();
if(con == null){
con = DriverManager.getConnection();
local.set(con);
}
return con;
}

public static void closeConnection(){
Connection con = (Connection) local.get();
if(con != null){
con.close();
}
local.set(null);
}

}


在使用时直接用:
Connection con = UtilConnection.getCurrentConnection();
不知道这样好不好,没测试过,高手说下,这样做可以不.
lzheng2001 2007-11-28
  • 打赏
  • 举报
回复
上面打错字了:
"实际上是经常tomcat连接池处理" => "实际上是经过tomcat连接池处理"
lzheng2001 2007-11-28
  • 打赏
  • 举报
回复
to bao110908: 你是说tomcal本身就有这个功能了吗? 我根本不用管连接池这部分吗?
比如说:我执行以下代码,实际上是经常tomcat连接池处理,并不是直接连接或断开数据库,对吗? 如果是, 按照4楼所说原理,我执行close()后,只是与tomcat连接池断开联系,实际上并不是与数据库断开连接.
connection = DriverManager.getConnection(dburl, uid, pwd)
connecttion.close()
  • 打赏
  • 举报
回复
如果是Web应用的话,不建议自己来管理连接池,一般使用应用服务器的JNDI数据源来配置连接池,
让应用服务器来管理。像Tomcat的JNDI数据源底层就是使用DBCP来实现的。
  • 打赏
  • 举报
回复
不知道java本身有没有专门处理连接池相关的类?
________________________________________

有的,DBCP和C3P0都是相当不错的连接池开源框架:
DBCP http://commons.apache.org/dbcp/
C3P0 http://sourceforge.net/projects/c3p0
chenggm 2007-11-28
  • 打赏
  • 举报
回复
好像apache就写过连接池
lzheng2001 2007-11-28
  • 打赏
  • 举报
回复
以前搞CS系统为主的,一般一个客户端一个连接,系统同时使用的用户不算多,所以没用上连接池. 现在搞BS程序,我就觉得可能连接池很有必要了, 太多的connect及disconnect操作会影响数据库性能,用户越多问题越严重.
lzheng2001 2007-11-28
  • 打赏
  • 举报
回复
谢谢大家.
to lip009: 连接池是很好的方案,不知道java本身有没有专门处理连接池相关的类? 我用过其它一些开发工具,有专门的连接池(类).

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧