jfinal并发的事务死锁问题

jeffw 发布于 2015/02/06 18:12
阅读 1K+
收藏 0

@jfinal   

有一个controller,请求方法test,test加了事务@Before(TxSerializable.class)

有TableA,字段count

public class TableA extends Model<TableA> {
    public static final TableA dao=new TableA();

        public  void test() {
                TableA tableA=findById(1);
                int count=tableA.getInt("count");
                if(count>0){
                     tableA.set("count",count-1).update();
                     System.out.println("count:"+count);
                }
        }
}



部署一个tomcat,测试500个并发,60秒,这个写法测试没有问题

如果部署3个tomcat,测试500个并发,60秒,测试也没有问题,tomcat3会正确的走下去,tomcat1与tomcat2会报Deadlock found when trying to get lock;异常

去数据库看了下LATEST DETECTED DEADLOCK 

我猜想应该是这种情况:

tomcat1,请求test,update tableA set count=9 where id=1;  开启事务A对tablea加锁

tomcat2,请求test,update tableA set count=8 where id=1;开启事务B发现tablea已被加锁,就等待

tomcat3,请求test,update tableA set count=8 where id=1;开启事务C发现tablea已被加锁,就等待

当事务A完成,事务B发现事务C对tablea加了锁,事务B发现事务C对tablea加了锁,所以出现了死锁,

mysql让事务B回滚,事务C执行commit

不知道我理解的有没有误,tomcat集群,如何去解决这种死锁


加载中
0
JFinal
JFinal

     mysql 事务有可能发生死锁,死锁也不一定只出现在集群之下,单个 tomcat 多线程也是类似的情况。这个问题本质上是 mysql 数据库死锁的范畴了,建议使用 Db.update("update ....) 并且事务级别使用 TxRepeatableRead 来解决问题。

   楼主的代码先是通过 findById 读取出了数据,然后再通过 tableB.set("count", count - 1).update() 写入库,这类将数据先从库里面读出来,在内存中操作以后,再往库里面写的方式本身就会对事务级别要求提升至少一个等级,是不合算的,或许也增加了死锁的机率。

   建议直接 Db.update("update tableA set count = count -1 where id=?", id) 这样做既能提升效率,又能降低事务级别要求,还能降低死锁机率。测试下反馈给我

铂金蛋蛋
铂金蛋蛋
+1
0
徐迎龙
徐迎龙
这和jfinal 油漆么关系
jeffw
jeffw
我可至始至终没说和jfinal有关系,我只是说讨论下
返回顶部
顶部