问一个spring事务的问题

「已注销」 2018-09-19 02:25:26
异常现象如下:

2018-09-18 16:46:04:748 [http-nio-9090-exec-4] [INFO] - org.springframework.beans.factory.xml.XmlBeanDefinitionReader(loadBeanDefinitions:316) - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2018-09-18 16:46:04:787 [http-nio-9090-exec-4] [INFO] - org.springframework.jdbc.support.SQLErrorCodesFactory(<init>:126) - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
2018-09-18 16:46:04:802 [http-nio-9090-exec-4] [INFO] - com.sun.proxy.$Proxy166(afterThrowing:25) - **************************************************************
2018-09-18 16:46:04:802 [http-nio-9090-exec-4] [INFO] - com.sun.proxy.$Proxy166(afterThrowing:26) - 代理对象: com.sun.proxy.$Proxy166
2018-09-18 16:46:04:803 [http-nio-9090-exec-4] [INFO] - com.sun.proxy.$Proxy166(afterThrowing:27) - 发生异常方法: getById
2018-09-18 16:46:04:803 [http-nio-9090-exec-4] [INFO] - com.sun.proxy.$Proxy166(afterThrowing:29) - 方法参数[0]: 4795
2018-09-18 16:46:04:803 [http-nio-9090-exec-4] [INFO] - com.sun.proxy.$Proxy166(afterThrowing:29) - 方法参数[1]: true
2018-09-18 16:46:04:804 [http-nio-9090-exec-4] [INFO] - com.sun.proxy.$Proxy166(afterThrowing:31) - 异常名称: org.springframework.dao.CannotAcquireLockException
2018-09-18 16:46:04:804 [http-nio-9090-exec-4] [INFO] - com.sun.proxy.$Proxy166(afterThrowing:32) - 异常信息:
### Error querying database. Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction

====================

首先,异常的原因我已经知道,因为另外一个事务里把数据锁住了,但是事务一直没提交,所以select for update 的锁没释放,导致等待超时了。

但是,另外一个事务为什么没提交的原因没弄明白。


时间顺序大概是这个样子,事务1已经处理完了,到事务的最后一步了,可是卡在这里了。一直等到五分钟之后才成功。
事务2,事务3都是再去找select for update 数据的时候,悲观锁没释放导致查不到数据超时了,然后超时之后就抛出异常了。

我的问题是事务1已经处理完了,整个方法的最后一步都执行完了可就是迟迟没有走到事务外层方法,所以也就一直没有commit成功。但是这个节点应该已经没有阻碍它提交的东西了,为什么一直提交不上去呢?
...全文
173 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2018-09-20
  • 打赏
  • 举报
回复
DBA说是数据库磁盘空间不够


但是事务过了五分钟又提上去了,我猜测应该是数据库的缓存不够了,被其他线程占用了,然后过了一段时间其他线程释放了,所以就提上去了。
「已注销」 2018-09-19
  • 打赏
  • 举报
回复
怀疑1:spring或者mysql在做事务提交的时候对于相同资源的CRUD有排他性,也就是相同资源的操作是单例的。(这种可能性不大)
怀疑2:程序中出现逻辑死锁。比如 有两个并发事务,事务1:lock A-->事务2:lock B--> 事务1 lock B(不能lock,等待)-->事务2:lockA(不能lock,等待),这样两个事务会互相等待。一直到事务超时。(但检查代码没有发现这种)
怀疑3:问题中提到的事务1可能因为某种原因被直接挂起了,(也许资源不够,数据库暂时失去链接等),然后因为事务1一直占用资源不释放,就导致其他访问该资源的线程直接没法执行了。

怀疑4:与select for update无关。 是访问其他资源出的问题
icarusliu81 2018-09-19
  • 打赏
  • 举报
回复
程序设计估计存在问题。最好将代码放出来看看。现有信息判断不了
My_Pass_Word 2018-09-19
  • 打赏
  • 举报
回复
你这种问题应该偶尔出现一次把,这种不能重现的情况我一般会回复客户说:"把你们的操作步骤导致出现的问题说一下,如果不能重现我就回复重现不了,以后慢慢再找",拖字诀,影响不大就行
「已注销」 2018-09-19
  • 打赏
  • 举报
回复
引用 2 楼 My_Pass_Word 的回复:
有时候不是程序的原因,百度一下你用的是哪个数据库是否锁表了,把锁的表释放了,在简单一点就是重启数据库,然后你再走一下程序看一下。
一般造成数据库锁表是程序引起的,不过一般问题不大


没有锁表,因为最终事务1提交成功了。所以2,3报错了,1 成功了。最终结果是正确的。

我观察是用户执行了1,结果卡住了,然后又刷新执行了2,又卡住,又刷新执行了3。
都是对同一条数据的操作。

但是这个事务比较大,涉及到十条左右的数据更新/插入吧。
「已注销」 2018-09-19
  • 打赏
  • 举报
回复
引用 1 楼 icarusliu 的回复:
事务1在做什么事情?
事务1 2 3 是执行的同一个方法,并发执行了。不过这个时间线看日志的话事务1执行完了才走到2 3
My_Pass_Word 2018-09-19
  • 打赏
  • 举报
回复
有时候不是程序的原因,百度一下你用的是哪个数据库是否锁表了,把锁的表释放了,在简单一点就是重启数据库,然后你再走一下程序看一下。 一般造成数据库锁表是程序引起的,不过一般问题不大
icarusliu81 2018-09-19
  • 打赏
  • 举报
回复
事务1在做什么事情?

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧