DataSource相关事务处理的一个问题

来源:互联网 发布:linux 搭建php服务器 编辑:程序博客网 时间:2024/05/17 03:04

在现在的OR方案和SPRING JDBC框架中,对数据库事务处理均是对java.sql.DataSource处理的。

大致思路是:在开始事务时,事务管理器会记录DataSource的连接,以后每个DAO从DataSource中getConnection()时,事务管理器会判断这个Connection是不是当前控制事务的子线程打开的,如果是,则记录并对此Connection进行事务处理,在commit和rollback事务时,会对所有打开的Connection进行Commit和rollback,最终清理所有Connection资源。

大伙可能知道,数据库对事务缓存是按会话区分的。一个Connection就是一个会话。举例说明:

maxid 1  

for(A、B){

    1:取maxid;

    其他操作

    2:更新maxid++;

}

这假设的A、B两个完全相同的业务操作。每个操作下又有1、2两个DAO操作。

   在执行 A.1时,取出最大值maxid=1

   执行   A.2时,更新成maxid=2

   扫行   B.1时,取出最大值max=? 这正确的应该是2,而实际取到的是1

这就有一个问题,B.1的结果是错误的。分析原因:因为上面三个步骤可能都是单独的Connection,在执行A.2后,该事务并未提交(因为大的事务未完成),更新仅在A.2打开连接中有效。B.1操作时,数据库返回的是之前有效的结果。

 

解决方案:1、将AB拆分成两个事务。

          2、自已在程序中记录maxid

          3、改变代码,不让DAO每次去取新的Connection,而在事务前开一个连接,所有DAO操作均在此Connection内完成。事务也中针对这个Connection。

 

这有多个操作,每个操作中第一个小操作是先取maxid,最后更新maxid++。

由于spring/hibernate/ibatis中均是对事务处理,每个DAO操作均可能新开连接。

取maxid可能是一个连接,更新maxid又可能是另一个连接。以后的操作另开的连接。

原创粉丝点击