seata事務隔離

官網解釋
https://seata.io/zh-cn/docs/user/appendix/isolation.html
看官網之前一定要分清官網中說的全局事務和本地事務,本地事務就是平時開發的時候
用@Transactional標注的方法,執行多個sql保證統一提交,利用的是數據庫自身的事務
全局事務就是seata自帶的事務,跨服務的事務,這兩個分不清理解不好隔離,
在debug的時候,不要debug全部線程,因為有心跳到nacos,超過30秒就下線了,就會發生Feign找不到服務

image.png

1.本地事務修改了全局事務的數據,回滾問題
image.png

T1為全局事務,T2為本地事務
T1修改庫存之后,還要生成訂單,當生成訂單的時候發生異常,但是T2本地事務不受全局事務的限制直接修改了庫存,T1回滾庫存服務的時候就異常,會一直重試直到超時.超時時間通過配置
server.maxRollbackRetryTimeout=-1 -1代表永不超時
測試
T1事務


image.png

T2調用庫存服務修改庫存數據


image.png

全局事務服務發起調用
image.png

T1修改庫存服務之前剩余80
image.png

T1調用訂單服務時debug,是要拋出異常的


image.png

T1修改庫存剩余78,雖然T1此時沒有提交全局事務,但是庫存數據庫已經提交(AT模式特性)


image.png

T2事務
修改庫存(此時T1還沒有提交,debug阻塞在生成訂單服務)
image.png

數據庫修改數據由78修改76


image.png

T1服務debug放開,因為拋出異常,通過TC通知庫存服務重試回滾數據,因為修改后的數據為78,回滾的是判斷當前數據是否為78,但是當前已經被T2修改未76,一直重試回滾,當我們手動的修改數據庫為78時,具備回滾條件,將數據修改為T1事務之前的數據80
image.png
2.兩個全局事務

示例1提到了,本地事務可以修改全局事務的數據,那能不能像本地事務那樣阻塞住,T2等T1全局事務提交后,再繼續執行T2呢,答案是可以的,只要將T2升級為全局事務,只是標注
@GlobalTransactional就可以了
在本地測試的時候,記著把垃圾數據清理,比如lock_table表,undolog表的數據都清理一下,不清理會提示數據被鎖的給錯誤信息
當T2標注@GlobalTransactional就會提示錯誤


image.png

超時了,也是通過配置實現的,重試30次,每次10毫秒
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
找了一下重試超時的源碼,像這種一定是while(true)或者for(;;)加異常退出的方式
io.seata.rm.datasource.exec.LockRetryController#sleep

3.T1T2都為全局事務,T2為全局讀

上面兩個例子是寫隔離,那讀隔離呢
AT模式,都是先將數據commit,在回滾的時候才會把數據通過補償的方式恢復,
如果T2為全局事務讀取庫存數據,查詢語句為select * from stock where id = 1,
當T1全局事務還沒有提交的時候,但是庫存其實已經修改了,T2讀取的也是修改之后的數據
其實希望的是,T1全局事務沒有提交,即使庫存數據已經修改了,還想讀取未修改之前的數據,
官網上提到了 使用 for update的方式,這里就不詳細的說明了,在git上都有,postman的請求也會發到git上

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容