关于Spring事务的死锁问题,还请大神指教

noneofmm 2017-11-10 12:55:52
先说下环境,使用springMVC ,mybatis,mysql(默认隔离级别)
上代码:
@Autowired
private UserMapper userDao;

@Transactional
@RequestMapping(value = "/trxAdd.do", method = RequestMethod.GET)
public void getAccountAdd(HttpServletRequest request, HttpServletResponse response) throws Exception {
logger.info("add trx start");
cdl.await();
Map result=Helper.initResponse();
User user=userDao.selectByPrimaryKey(1); //select * from langcom where uid=1 uid 为pk
if(user.getUsername().equals("h18x")){
user.setUsername("xxx");
user.setCash(88888l);
userDao.updateByPrimaryKey(user);
}else{
result.put("message", "Add事务执行失败");
}

logger.info("add end");;
Helper.restful(response, result);


}
@Transactional
@RequestMapping(value = "/trxRemove.do", method = RequestMethod.GET)
public void getAccountRemove(HttpServletRequest request, HttpServletResponse response) throws Exception {
logger.info("remove trx start");
cdl.await();
Map result=Helper.initResponse();
User user=userDao.selectByPrimaryKey(1);
if(user.getUsername().equals("h18x")){
user.setUsername("xxx");
user.setCash(200l);
userDao.updateByPrimaryKey(user);
}else{
result.put("message", "Remove事务执行失败");
}

logger.info("remove end");;
Helper.restful(response, result);
}


@RequestMapping(value = "/trxStart.do", method = RequestMethod.GET)
public void getAccountStart(HttpServletRequest request, HttpServletResponse response) throws Exception {
cdl.countDown();
logger.info("count start end");
Helper.restful(response, Helper.initResponse());

}

执行方式很简单,执行 trxadd.do trxRemove.do 后 在执行trxStart.do ,结果产死锁问题。
怀疑如下:
1.之前有想过,是否是事务开始时,查询selectByPrimaryKey()时,两个线程对单条记录加了S锁,后续在updateByPrimaryKey()方法时,要加X锁,导致需要对方释放S锁,所以产生死锁问题。但是 使用双线程进行debug,其中add先执行至条件判断(即已经读取,猜测获取到了 S锁) ,然后换另一个线程执行update语句,毫无问题。所以之前猜想失败,select时,是没有S锁的加持。
2. 后续使用mysql客户端,开启事务,(
begin;
update langcom set cash=100 where uid= 1;
)并不提交,然后执行trxadd.do, 发现selectByPrimaryKey()查询毫无问题,但是在执行updateByPrimaryKey()方法时,会因为请求X锁挂起,但由于Spring的机制,会有一个事务超时的异常,而终止该线程。

那么问题来了,到底是什么导致了,双线程并行争抢导致的死锁问题呢?还请大神指教
...全文
877 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
lsongiu86 2017-11-10
  • 打赏
  • 举报
回复
数据库的死锁不是这样产生的,应该不是数据库事务的问题,看看你的CountDownLatch的count是多少,多请求几次trxStart.do,把count先变成0试试
繁华终归落尽 2017-11-10
  • 打赏
  • 举报
回复
感觉像是计数器引起的,代码贴全一点看看
X元素 2017-11-10
  • 打赏
  • 举报
回复
楼主尝试非debug运行,通过http请求访问接口,看看是否存在该问题。 另外楼主可以通过TransactionAspectSupport 获取当前事务状态,

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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