Seata 1.5.2 源碼學習( 四 )


ConnectionProxy#changeAutoCommit()

Seata 1.5.2 源碼學習

文章插圖
現在事務自動提交已經被Seata改成false了
Seata 1.5.2 源碼學習

文章插圖
UpdateExecutor#beforeImage()
Seata 1.5.2 源碼學習

文章插圖
BaseTransactionalExecutor#prepareUndoLog()
Seata 1.5.2 源碼學習

文章插圖
接下來,提交事務
ConnectionProxy#commit()
Seata 1.5.2 源碼學習

文章插圖
ConnectionProxy#processGlobalTransactionCommit() 處理全局事務提交
Seata 1.5.2 源碼學習

文章插圖
分支事務提交以后,業務數據更改和undo_log就都提交了
回想一下,為什么在執行業務修改前要先將默認的自動提交改成手動提交 , 最后再改成自動提交呢?
因為 , 要將業務數據修改和插入undo_log放在同一個事務里,一起提交
這一切都歸功于代理
回顧一下整個調用鏈
Seata 1.5.2 源碼學習

文章插圖
結合之前的案例,AT模式TC、TM、RM三者的交互應該是這樣的:
Seata 1.5.2 源碼學習

文章插圖
問題一:為什么在執行的時候,先將數據庫自動提交autoCommit設為false,最后再改成true呢?
答:因為,需要將undo_log和業務數據修改放到同一個事務中,這樣可以保證業務數據修改成功后undo_log必然插入成功,所以Seata要將其改為手動提交 。最后再改成true是因為默認autoCommit就是true , 這樣可以不影響其它業務 。
問題二:什么情況下ConnectionContext中xid=null,且isGlobalLockRequire=true呢?或者換一種問法 , 什么情況下不在全局事務中 , 當仍然需要全局鎖呢?
答:當業務方法上不加@GlobalTransactional,而是只加了@GlobalLock注解的情況下 , 就會出現上述情況,也就會執行 ConnectionProxy#processLocalCommitWithGlobalLocks()方法,在事務提交前檢查全局鎖,這樣設計的目的是在AT模式下,不出現臟讀、臟寫 。由于數據源被代理了,當一個加了@GlobalTransactional的全局事務 , 與另一個加了@GlobalTransactional或@GlobalLock注解的事務在本地事務提交前就會檢查全局鎖 , 要先獲得全局鎖才能提交本地事務,這樣就避免了臟讀臟寫,從而相當于實現了全局事務的讀已提交隔離級別 。參見:https://seata.io/zh-cn/blog/seata-at-lock.html
關于Seata 1.5.2 Client端的源碼學習就先到這里,歡迎交流~
如果你都已經看到了這里 , 不妨給我點個贊吧

推薦閱讀