@Override @Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW) //我建议不要用这个注解,他是声明式事务粒度过大,建议用使用编程式事务,可控性高 public void generate() { //删除数据没有提交,然后操作其他 /** * 这是我参考stackoverflow上的。我猜测也是这样的,删除事务没有提交,然后操作插入,造成锁等待引起的死锁 * 一个线程进来锁表操作删除数据,恰好还没有提交数据让数据更新,紧接着其他线程进来准备操作,发现被之前的线程锁住了 * 他就等待其他线程释放锁,结果循环操作等待,大家都不释放锁相互占用资源。 * 解决方案:主动释放资源或者结束等待。 * 数据库事务隔离级别:通过此查出 SELECT * FROM information_schema.INNODB_TRX;-》REPEATABLE READ可重复读,可改为 commit * ‘Lock wait timeout’ occurs typically * when a transaction is waiting on row(s) of data to update * which is already been locked by some other transaction. * 1.缩小事务范围还是不能解决问题 * 2.事务失效,不能用try catch */ //经老夫排查有137页 ,每页1000条数据,引起删除超时,并非后面for循环,因为我的事务没有加在函数名上,我用局部事务,当时去了@Transactrionnal 也不行 long t1 = System.currentTimeMillis(); // transactionTemplate.execute(p->{ baseMapper.delete(Wrappers.emptyWrapper()); // return null; // }); //日常检查 List<SysUser> sysUsers = sysUserService.selectUserList(SysUser.builder().roleKeys(roleKeys).build()); for (SysUser sysUser : sysUsers) { //公司业务,我省了 baseMapper.insert(ltThreeCenterTeam); } //街道管理 for (SysUser sysUser : sysUsers) { baseMapper.insert(ltThreeCenterTeam); } //处置单位 //市政 for (SysUser sysUser : sysUsers) { baseMapper.insert(ltThreeCenterTeam); } //环卫 for (SysUser sysUser : sysUsers) { baseMapper.insert(ltThreeCenterTeam); } //绿化 for (SysUser sysUser : sysUsers) { baseMapper.insert(ltThreeCenterTeam); } long t2 = System.currentTimeMillis(); System.out.println( "耗时------------------"+(t2-t1));//耗时------------------51422 }
我去除了
@Transactional,使用粒度小的
transactionTemplate.execute(p->{
baseMapper.delete(Wrappers.emptyWrapper());
return null;
});
都不行,最后加大了锁等待超时时间才行的
#查询锁等待时间,默认为50s
show GLOBAL VARIABLES like 'innodb_lock_wait_timeout'
set GLOBAL innodb_lock_wait_timeout=500
网上也有一种解决方案,删除分批。我的业务暂时不太适应那种方式
本文来自博客园,作者:狂躁的键盘,转载请注明原文链接:https://www.cnblogs.com/wangweiip/p/16895178.html