当前位置: 首页 > 后端技术 > Java

@Transactional导致错误Lockwaittimeoutexceeded

时间:2023-04-02 00:07:36 Java

@Transactional导致错误Lockwaittimeoutexceeded;尝试重启事务前言最近网上项目报Lockwaittimeoutexceeded;尝试重启事务检查百度锁超时超时;tryrestartingtransaction大概意思就是,也就是mysql出现了死锁。需要查看当前进程showfullprocesslist;检查mysql锁表select*frominformation_schema.innodb_trx;这里的结果需要关注trx_state和trx_mysql_thread_id这两个字段。以上结果,去掉trx_state=LOCK_WAIT的结果,证明mysql没有死锁。迷茫,不知道怎么解决。监控mysql,不断刷新showfullprocesslist;无意中找到一条sql查询语句,又继续执行。进入系统查看这条sql语句。发现系统中的一个服务方法上使用了@Transactional。那么问题就来了。为什么使用@Transactional会报Lockwaittimeoutexceeded;尝试重启事务猜测是否有任务,然后执行该方法,其他任务也会执行该方法。测试猜想写了两个方法,同时有select,update@Override@TransactionalpublicPersongetPerson(){System.out.println("getPerson1accessprogramstart:===========""+System.currentTimeMillis());Personperson=getById(1);System.out.println(person.getName());person.setName("测试"+System.currentTimeMillis());updateById(person);try{Thread.sleep(100000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("getPerson1访问程序结束:===========""+System.currentTimeMillis());归还人;}@Override@TransactionalpublicPersongetPerson2(){System.out.println("getPerson2访问程序开始:===========""+System.currentTimeMillis());Personperson=getById(2);System.out.println(person.getName());person.setName("TEST"+System.currentTimeMillis());updateById(person);try{Thread.sleep(100000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("访问程序结束:===========""+System.currentTimeMillis());returnperson;}写两个单元测试,分别请求@Testvoiddemo2(){personService.getPerson();}@Testvoiddemo3(){personService.getPerson2();}当结果getById()全为1时,getById重现()不同次数,不重现![1642411180281]![164241186155]结论@Transactional是行级锁mysql等待事务锁innodb_lock_wait_timeout默认50s使用事务时,尽量简化服务代码