并发错误:事务(进程 ID )与另一个进程已被死锁在 lock 资源上,且该事务已被选作死锁牺牲品

这个是并发情况下导致的数据库事务错误,先介绍下背景。

背景

springboot+springmvc+sqlserver+mybatis

一个controller里有五六个接口,这些接口都用到了spring的事务管理,这些接口单个调用的时候都很正常,当我模拟几十个并发请求这些接口的时候,总会有一两次的mybatis的持久化操作会出错,具体错误:

nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.lang.reflect.UndeclaredThrowableException
### The error may involve com.xxxxxxxxx-Inline
### The error occurred while setting parameters
### SQL: update xxxx set ccccc = ?  ,jid = ? ,status = ?                                                                                         where bcode=? and status != 0
### Cause: java.lang.reflect.UndeclaredThrowableException

根据提示的这个UndeclaredThrowableException,到网上搜索都是说mybatis的映射文件里的字段属性与model里的写的不一致。

但是如果是写法不对的话,应该每次请求的都报错啊,现在是几十次里只有一两次报错,肯定不是这个原因。

在网上搜了半天,无果,于是把代码放到服务器上再模拟并发测试一下,还是会有一两次报错,不过这次报的错就很明朗了

### Error querying database.  Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 事务(进程 ID 62)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
### The error may exist in file [E:kkkkkxxxMapper.xml]
### The error may involve com.xxxxx.ppppp
### The error occurred while handling results
### SQL: SELECT b.* FROM xxxxx a RIGHT JOIN ooooo b ON a.GId = b.id  where a.bcode = '11111'
### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 事务(进程 ID 62)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
; SQL []; 事务(进程 ID 62)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: 事务(进程 ID 62)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

原来是并发引起的数据库事务报错,具体原因和修改看这篇:对于spring中事务@Transactional注解的理解

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

我了解了一下事务处理机制,原来这个错误是在数据库中抛出的。因为不同线程在事务中处理相同的数据时,数据库会采取让一个执行而另一个放弃执行,于是就出现上面的错了。之所以插入不容易出现这个错误,是因为插入的速度快,不容易出现。同时如果修改的时候按照条件修改数据速度就会慢,如果按照主键或索引修改速度就会快,也不容易出现这个错误。@xmt1139057136,虽然没给具体的方法确实是按照这个思路想出来的,谢谢啦。对了,我对TOMCAT在局域网内进行压力测试时,发现速度明显比本地慢的多,而且无法处理并发1000条了(本机是可以的),向请教一下。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

解决方法

1.Spring异常重试框架Spring Retry

2.把事务的隔离级别改为宽松的,read_uncommited

原文地址:https://www.cnblogs.com/shamo89/p/9073797.html