apache / apache/incubator-seata
GlobalSession中对status的update操作没有加锁,在并发场景下可能会导致事务最终永远失败
- Dominant language
- Java
- Stars
- 26k
- Forks
- 8.8k
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 4
Description
- [x] I have searched the [issues](https://github.com/seata/seata/issues) of this repository and believe that this is not a duplicate.
### Ⅰ. Issue Description
DB存储模式下,GlobalSession中对status的update操作没有加锁,并发场景下可能会导致分布式事务永远不会成功
### Ⅱ. Describe what happened
**线程A:** 正常执行一个分布式事务,假设整个分布式事务执行时间较长,最终对应GLobalSession中的status状态还是被更新为commit,并且部分或者全部分支事务参与方已经执行commit操作成功。
**线程B:** 线程B为DefaultCoordinator中执行timeoutCheck的定时任务,假设timeoutCheck获取所有事务的时候线程A的GlobalSession还是Begin状态,由于该GlobalSession执行时间较长被判定为超时,此时就可能在线程A更新为commit状态之后重新被更新为TimeoutRollbacking,然后由其他定时任务开始执行回滚操作。
这样就会导致GlobalSession的状态从begin -> commit -> TimeoutRollbacking。而在这个过程中一些事物参与方已经执行过commit了,再次被要求执行rollback时就可能会报错,并且永远不会成功,事务会一直处于中间状态(一部分参与方已经提交,一部分参与被要求回滚,全局事务被标记为回滚)
```
Just paste your stack trace here!
```
### Ⅲ. Describe what you expected to happen
对事务状态的更新需要考虑并发问题,个人认为任何场景下事务允许失败,但是不能处于一个坏的、不可恢复的状态。
### Ⅳ. How to reproduce it (as minimally and precisely as possible)
并发场景,不容易复现。
1. xxx
2. xxx
3. xxx
### Ⅴ. Anything else we need to know?
### Ⅵ. Environment:
- JDK version :
- OS :
- Others:
Contributor guide
Research direction
Start by reading GlobalSession status updates and the DefaultCoordinator timeoutCheck path in DB storage mode. Trace concurrent commit and timeout handling, then verify that a transaction cannot move from commit to TimeoutRollbacking and remain unrecoverable under concurrent execution.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- databases, distributed-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100