@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集群,如何去解决这种死锁
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######这和jfinal 油漆么关系######我可至始至终没说和jfinal有关系,我只是说讨论下
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。