Mysql 死锁,但是执行过程却是null终极问题解决


Mysql 死锁,但是执行过程却是null终极问题解决

出现如下幽灵语句


这个表在这:


问题代码:

/**
	 * 对投注项目进行投注
	 * @param roomId
	 * @param gameId
	 * @param gameItemId
	 * @param putScore
	 * @param multiPower
	 * @param req
	 * @return
	 */
	@SuppressWarnings("unused")
	@At("/betQBH")
	@Authentication(checkarea=AuthenticationType.session)
	@POST
	public Object betQBH( @Param("roomId")String roomId, @Param("gameId")String gameId, 
			@Param("gameItemId")String gameItemId, @Param("putScore")Integer putScore, @Param("multiPower")Double multiPower, HttpServletRequest req) {
		try {

			//这个选项是没有用的
			multiPower = 1.00d;
			// 校验空错误
			ApiResult checkResult = QBH_ResultUtil.checkStringParamWhenError(QBH_ResultUtil.getResultError(),
					new String[] {  "roomId参数错误" ,"gameId参数错误","gameItemId参数错误"}, new String[] { roomId,gameId,gameItemId});
			if (checkResult != null)
				return checkResult;

			Member mb = (Member) req.getAttribute("member");
			Game game = gameService.fetch(gameId);
			//竞猜项目状态为 0停止投注 及 2已结算的会列出来,但不能投注
			if (game.getState() == null) game.setState(1);
			if (game.getState() == GameConstants.GG_STATE_CANNOTBET) {
				return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "此竞猜项目暂时停止投注",new JsonObject());
			}
			if (game.getState() == GameConstants.GG_STATE_CLOSING) {
				return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "此竞猜项目已结算",new JsonObject());
			}
			//jonathan add
			/*GameSchedule gameSchedule=gameScheduleService.fetch(game.getMatchId());
			if(gameSchedule==null || gameSchedule.getState()==GameConstants.GS_STATE_GAMEOVER)
			{
				return ApiResult.New(ReturnCode.ERROR).addMsg("此竞猜项目暂时停止投注");
			}*/
			GameItem item=gameItemService.fetch(gameItemId);
			if (item.getState() == null) item.setState(1);
			if (item.getState() != GameConstants.GG_STATE_CANBET) {
				return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "此竞猜项目暂时停止投注",new JsonObject());
			}
			/*if(multiPower==null || StringUtils.isBlank(item.getOdds())||multiPower.doubleValue()!=Double.valueOf(item.getOdds()))
			{
				return ApiResult.New(ReturnCode.ERROR).addMsg("此竞猜项目赔率已发生变化,请重新下注!"+multiPower+"-"+item.getOdds());
			}*/
			// 查询该用户是否已经投注过该竞猜项目(竞猜的其中一种结果),有返回true,无返回false
			/*int alrdyBetCnt = roomMembersBetService.count(Cnd.NEW().and("memberId", "=", mb.getId()).and("gameItemId", "=", gameItemId).and("gameId", "=", gameId));
			if (alrdyBetCnt > 0) {
				return ApiResult.New(ReturnCode.ERROR).addMsg("竞猜项目不支持重复投注");
			}*/

			// 验证投注积分值处于有效范围
			if (putScore<game.getMinScore() || putScore>game.getMaxScore()) {
				return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "投注积分区间["+game.getMinScore()+" - "+game.getMaxScore()+"]",new JsonObject());
			}
			try
			{
				Trans.begin();
				//betInner( roomId, game, item, putScore, multiPower, req);
				// 查询该房间的所在赛程的ID
				String scheduleId = game.getMatchId();
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				mb = memberService.fetch(mb.getId());// 从数据库中读出新数据。
				// 首页、房间投注逻辑
				if (Strings.isBlank(roomId) || roomId.equals("0") || roomId.trim().equals("")) { // 首页投注
					if (mb.getTotalScore() < putScore) {
						return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "成员当前总积分:" + mb.getTotalScore() + " 小于投注积分数:" + putScore + "",new JsonObject());
					}
					mb.setTotalScore(mb.getTotalScore() - putScore);
				} else { // 房间投注
					// (判断大小房:0大房 1小房) 前边括号注释的逻辑失效
					int roomType = roomService.query(Cnd.NEW().and("id", "=", roomId)).get(0).getType();
					if (mb.getTotalScore() < putScore) {
						return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "积分不足!缺少 " + (putScore - mb.getTotalScore()) + "积分" + putScore + "",new JsonObject());
					}
					mb.setTotalScore(mb.getTotalScore() - putScore);
					/*if (roomType == RoomConstants.RR_TYPE_BIG) { // 大房投注的积分直接扣除
						if (mb.getTotalScore() < putScore) {
							throw new Exception("积分不足!缺少 " + (putScore - mb.getTotalScore()) + "积分");
						}
						mb.setTotalScore(mb.getTotalScore() - putScore);
					} else { // 小房只允许用 冻结积分表的可用积分进行投注

						RoomMembersSealInfo sealInfo = roomMembersSealInfoService
								.fetch(Cnd.NEW().and("membersId", "=", mb.getId()).and("roomId", "=", roomId));
						if (sealInfo != null) {
							if (sealInfo.getAvlScore() < putScore) {
								throw new Exception("房间内可用积分不足!缺少 " + (putScore - sealInfo.getAvlScore()) + "积分");
							}
							sealInfo.setAvlScore(sealInfo.getAvlScore() - putScore);
							roomMembersSealInfoService.update(sealInfo);
						} else {
							// return ApiResult.New(ReturnCode.ERROR).addMsg("请重新进入房间");
							throw new Exception("请重新进入房间");
						}
					}*/
				}
				
				int count = Integer.parseInt(mb.getBetCount()) + 1;
				mb.setBetCount(count + "");
				memberService.update(mb);
				RoomMembersBet membersBet = new RoomMembersBet(mb.getId(), roomId, game.getId(), item.getId(), scheduleId, 0,
						putScore, sdf.format(new Date(System.currentTimeMillis())), multiPower);
				RoomMembersBet roomMembersBet = roomMembersBetService.insert(membersBet);
				// 积分记录表 插入一条积分消费记录
				memberScoreRecordService.insert(new MemberScoreRecord(mb.getId(), "投注" + putScore + "积分",
						MemberConstants.MSR_TYPE_EXPEND, putScore.longValue(), 0l, roomMembersBet.getId(), roomId));
				Trans.commit();
			}
			catch (Exception ex) {
				Trans.rollback();
				ex.printStackTrace();
				log.error("投注发生错误:" + ex.getMessage());
				return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "投注发生错误,请联系管理员",new JsonObject());
			} finally {
				Trans.close();
			}
			return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultSuccess(), ReturnCode.SUCCESS.getCode(), "投注成功",new JsonObject());
		} catch (Exception e) {
			e.printStackTrace();
			log.error("投注发生错误:"+e.getMessage());
			return QBH_ResultUtil.getResult(QBH_ResultUtil.getResultError(), ReturnCode.ERROR.getCode(), "投注发生错误,请联系管理员",new JsonObject());
		}
	}


简单而言,就是一个过程

Trans.begin();
   return ;

Trans.commit();
Trans.rollback();
Trans.close();

事物执行的载体方法,被return语句从方法堆栈中移除了,但是mysql的事物并没有被结束掉


解决方法很简单:

return之前,关闭事物(回滚也可,根据业务)

总而言之,不要轻易在开启事物过程中return





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值