java并发事务相关总结

1.@transcational注解和锁同时使用会造成锁失效的问题

以下是伪代码

class aSevice{
	
	// 方式一  synchronized 给事务加锁
	@Transactional(rollbackFor = Exception.class)
	public synchronized Response updateXNum(){
		//当前数据库读取Num数
		int currentNum = XXDao.getCurrentNum();
		//更新
		XXDao.updateNum(currentNum)
	}

	// 方式二  Lock手动上锁
	@Transactional(rollbackFor = Exception.class)
	public Response updateXNum(){
		Lock.lock();
		try{
		//当前数据库读取Num数
		int currentNum = XXDao.getCurrentNum();
		//更新
		XXDao.updateNum(currentNum)
		}catch(Exception e){
		}finally{
		  Lock.unlock();
		}
	}

}

上面这两种方式给添加的事务的方法加锁都是无效的,原因在于Transactional注解使用了AOP动态代理,当锁释放时代理的事务还未结束就又有新的线程进来,造成事务未提交而又开始读取数据操作数据库的问题

解决方案:让锁的范围大于事务包扩的范围即可


// 再用一个方法去调用被打上事务注解的方法,本方法加上synchronized同步锁 
	public synchronized Response updateXNum(){
		return updateXNumRepo();
	}
	
	@Transactional(rollbackFor = Exception.class)
	public Response updateXNumRepo(){
		//当前数据库读取Num数
		int currentNum = XXDao.getCurrentNum();
		//更新
		XXDao.updateNum(currentNum)
	}


   //Lock方式的同步锁也是同理
	public Response updateXNum(){
	Lock.lock();
		try{
		return updateXNumRepo();
		}catch(Exception e){
		}finally{
		  Lock.unlock();
		}
	}
	
	@Transactional(rollbackFor = Exception.class)
	public Response updateXNumRepo(){
		//当前数据库读取Num数
		int currentNum = XXDao.getCurrentNum();
		//更新
		XXDao.updateNum(currentNum)
	}

1.1 注意,还没有完结,针对上面的解决方案,如果是在同一个事务中非事务方法调用事务方法将会出现事务失效的问题。

上面的updateXNum()调用 updateXNumRepo()方法的时候,此时就算updateXNumRepo方法打了事务注解,但他的事务还是会失效,属于spring代理的时候,代理对象机制问题。
若要解决这个问题,updateXNum需要写在另一个serviceA中,再用serviceA.updateXNum()方法,或者注入自己本身service再调用也可以 代码如下:

	class AServiceImpl implements AService{

	// 注入一下本service对象去调用  解决同一个service中非事务方法调用事务方法,事务失效问题。
	@Autowired
	private AService  aservice;

// 再用一个方法去调用被打上事务注解的方法,本方法加上synchronized同步锁 
	public synchronized Response updateXNum(){
		// 在此处通过新注入aservice去调用即可解决
		return aservice.updateXNumRepo();
	}
	
	@Transactional(rollbackFor = Exception.class)
	public Response updateXNumRepo(){
		//当前数据库读取Num数
		int currentNum = XXDao.getCurrentNum();
		//更新
		XXDao.updateNum(currentNum)
	}
}

2.Mysql开启事务时update操作锁表的行为

1.查看自己当前的数据库是否开启了自动提交事务。

select @@autocommit;

若为 1 要设置为 0 关闭自动提交事务。

mysql开启事务在update操作的时候会锁表

1.若update的字段没有索引,则会锁住整张表

2.如果加了索引,则只会锁这一行。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值