国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - 編程技術 - 詳解 Seata AT 模式事務隔離級別與全局鎖設計

詳解 Seata AT 模式事務隔離級別與全局鎖設計

2021-12-27 23:25后端進階張乘輝 編程技術

Seata AT 模式是一種非侵入式的分布式事務解決方案,Seata 在內部做了對數據庫操作的代理層,我們使用 Seata AT 模式時,實際上用的是 Seata 自帶的數據源代理 DataSourceProxy,Seata 在這層代理中加入了很多邏輯,比如插入回滾 undo_log 日

詳解 Seata AT 模式事務隔離級別與全局鎖設計

Seata AT 模式是一種非侵入式的分布式事務解決方案,Seata 在內部做了對數據庫操作的代理層,我們使用 Seata AT 模式時,實際上用的是 Seata 自帶的數據源代理 DataSourceProxy,Seata 在這層代理中加入了很多邏輯,比如插入回滾 undo_log 日志,檢查全局鎖等。

為什么要檢查全局鎖呢,這是由于 Seata AT 模式的事務隔離是建立在支事務的本地隔離級別基礎之上的,在數據庫本地隔離級別讀已提交或以上的前提下,Seata 設計了由事務協調器維護的全局寫排他鎖,來保證事務間的寫隔離,同時,將全局事務默認定義在讀未提交的隔離級別上。

Seata 事務隔離級別解讀

在講 Seata 事務隔離級之前,我們先來回顧一下數據庫事務的隔離級別,目前數據庫事務的隔離級別一共有 4 種,由低到高分別為:

  • Read uncommitted:讀未提交
  • Read committed:讀已提交
  • Repeatable read:可重復讀
  • Serializable:序列化

數據庫一般默認的隔離級別為讀已提交,比如 Oracle,也有一些數據的默認隔離級別為可重復讀,比如 Mysql,一般而言,數據庫的讀已提交能夠滿足業務絕大部分場景了。

我們知道 Seata 的事務是一個全局事務,它包含了若干個分支本地事務,在全局事務執行過程中(全局事務還沒執行完),某個本地事務提交了,如果 Seata 沒有采取任務措施,則會導致已提交的本地事務被讀取,造成臟讀,如果數據在全局事務提交前已提交的本地事務被修改,則會造成臟寫。

由此可以看出,傳統意義的臟讀是讀到了未提交的數據,Seata 臟讀是讀到了全局事務下未提交的數據,全局事務可能包含多個本地事務,某個本地事務提交了不代表全局事務提交了。

在絕大部分應用在讀已提交的隔離級別下工作是沒有問題的,而實際上,這當中又有絕大多數的應用場景,實際上工作在讀未提交的隔離級別下同樣沒有問題。

在極端場景下,應用如果需要達到全局的讀已提交,Seata 也提供了全局鎖機制實現全局事務讀已提交。但是默認情況下,Seata 的全局事務是工作在讀未提交隔離級別的,保證絕大多數場景的高效性。

全局鎖實現

AT 模式下,會使用 Seata 內部數據源代理 DataSourceProxy,全局鎖的實現就是隱藏在這個代理中。我們分別在執行、提交的過程都做了什么。

1、執行過程

執行過程在 StatementProxy 類,在執行過程中,如果執行 SQL 是 select for update,則會使用 SelectForUpdateExecutor 類,如果執行方法中帶有 @GlobalTransactional or @GlobalLock注解,則會檢查是否有全局鎖,如果當前存在全局鎖,則會回滾本地事務,通過 while 循環不斷地重新競爭獲取本地鎖和全局鎖。

  1. public T doExecute(Object... args) throws Throwable {
  2. Connection conn = statementProxy.getConnection();
  3. // ... ...
  4. try {
  5. // ... ...
  6. while (true) {
  7. try {
  8. // ... ...
  9. if (RootContext.inGlobalTransaction() || RootContext.requireGlobalLock()) {
  10. // Do the same thing under either @GlobalTransactional or @GlobalLock,
  11. // that only check the global lock here.
  12. statementProxy.getConnectionProxy().checkLock(lockKeys);
  13. } else {
  14. throw new RuntimeException("Unknown situation!");
  15. }
  16. break;
  17. } catch (LockConflictException lce) {
  18. if (sp != null) {
  19. conn.rollback(sp);
  20. } else {
  21. conn.rollback();
  22. }
  23. // trigger retry
  24. lockRetryController.sleep(lce);
  25. }
  26. }
  27. } finally {
  28. // ...
  29. }

2、提交過程

提交過程在 ConnectionProxy#doCommit方法中。

1)如果執行方法中帶有@GlobalTransactional注解,則會在注冊分支時候獲取全局鎖:

  • 請求 TC 注冊分支
  1. private void register() throws TransactionException {
  2. if (!context.hasUndoLog() || !context.hasLockKey()) {
  3. return;
  4. }
  5. Long branchId = DefaultResourceManager.get().branchRegister(BranchType.AT, getDataSourceProxy().getResourceId(),
  6. null, context.getXid(), null, context.buildLockKeys());
  7. context.setBranchId(branchId);
  8. }
  • TC 注冊分支的時候,獲取全局鎖
  1. protected void branchSessionLock(GlobalSession globalSession, BranchSession branchSession) throws TransactionException {
  2. if (!branchSession.lock()) {
  3. throw new BranchTransactionException(LockKeyConflict, String
  4. .format("Global lock acquire failed xid = %s branchId = %s", globalSession.getXid(),
  5. branchSession.getBranchId()));
  6. }
  7. }

2)如果執行方法中帶有@GlobalLock注解,在提交前會查詢全局鎖是否存在,如果存在則拋異常:

io.seata.rm.datasource.ConnectionProxy#processLocalCommitWithGlobalLocks

  1. private void processLocalCommitWithGlobalLocks() throws SQLException {
  2. checkLock(context.buildLockKeys());
  3. try {
  4. targetConnection.commit();
  5. } catch (Throwable ex) {
  6. throw new SQLException(ex);
  7. }
  8. context.reset();
  9. }

GlobalLock 注解說明

從執行過程和提交過程可以看出,既然開啟全局事務 @GlobalTransactional注解可以在事務提交前,查詢全局鎖是否存在,那為什么 Seata 還要設計多處一個 @GlobalLock注解呢?

因為并不是所有的數據庫操作都需要開啟全局事務,而開啟全局事務是一個比較重的操作,需要向 TC 發起開啟全局事務等 RPC 過程,而@GlobalLock注解只會在執行過程中查詢全局鎖是否存在,不會去開啟全局事務,因此在不需要全局事務,而又需要檢查全局鎖避免臟讀臟寫時,使用@GlobalLock注解是一個更加輕量的操作。

如何防止臟寫

先來看一下使用 Seata AT 模式是怎么產生臟寫的:

詳解 Seata AT 模式事務隔離級別與全局鎖設計

注:分支事務執行過程省略其它過程。

業務一開啟全局事務,其中包含分支事務A(修改 A)和分支事務 B(修改 B),業務二修改 A,其中業務一執行分支事務 A 先獲取本地鎖,業務二則等待業務一執行完分支事務 A 之后,獲得本地鎖修改 A 并入庫,業務一在執行分支事務時發生異常了,由于分支事務 A 的數據被業務二修改,導致業務一的全局事務無法回滾。

如何防止臟寫?

1、業務二執行時加 @GlobalTransactional注解:

詳解 Seata AT 模式事務隔離級別與全局鎖設計

注:分支事務執行過程省略其它過程。

業務二在執行全局事務過程中,分支事務 A 提交前注冊分支事務獲取全局鎖時,發現業務業務一全局鎖還沒執行完,因此業務二提交不了,拋異常回滾,所以不會發生臟寫。

2、業務二執行時加 @GlobalLock注解:

詳解 Seata AT 模式事務隔離級別與全局鎖設計

注:分支事務執行過程省略其它過程。

與 @GlobalTransactional注解效果類似,只不過不需要開啟全局事務,只在本地事務提交前,檢查全局鎖是否存在。

2、業務二執行時加 @GlobalLock 注解 + select for update語句:

詳解 Seata AT 模式事務隔離級別與全局鎖設計

注:分支事務執行過程省略其它過程。

如果加了select for update語句,則會在 update 前檢查全局鎖是否存在,只有當全局鎖釋放之后,業務二才能開始執行 updateA 操作。

如果單單是 transactional,那么就有可能會出現臟寫,根本原因是沒有 Globallock 注解時,不會檢查全局鎖,這可能會導致另外一個全局事務回滾時,發現某個分支事務被臟寫了。所以加 select for update 也有個好處,就是可以重試。

如何防止臟讀

Seata AT 模式的臟讀是指在全局事務未提交前,被其它業務讀到已提交的分支事務的數據,本質上是Seata默認的全局事務是讀未提交。

那么怎么避免臟讀現象呢?

業務二查詢 A 時加 @GlobalLock 注解 + select for update語句:

詳解 Seata AT 模式事務隔離級別與全局鎖設計

注:分支事務執行過程省略其它過程。

加select for update語句會在執行 SQL 前檢查全局鎖是否存在,只有當全局鎖完成之后,才能繼續執行 SQL,這樣就防止了臟讀。

原文鏈接:https://mp.weixin.qq.com/s/Pwx9a1W3ANc4H4c-2TYkRQ

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 性色视频在线 | 久久国产精品久久精品 | 视频在线一区 | 欧美日韩精品一区二区三区蜜桃 | 成人性做爰av片免费看 | 在线观看黄 | 亚洲久草视频 | 91精品一区二区三区久久久久久 | 大象一区| 自拍视频在线 | 久久久久国产精品午夜一区 | 亚洲一区免费观看 | 一区二区在线 | 成人精品在线视频 | heyzo 在线| 草草成人| 九九热九九 | 91羞羞网站 | 亚洲国产精品免费 | 五月天婷婷综合 | 久久成人精品视频 | 91人人爽人人爽人人精88v | 午夜精品美女久久久久av福利 | 色玖玖综合| 亚洲精选久久 | 精品无码久久久久久国产 | 亚洲激情av | 精品国精品国产自在久不卡 | 国产精品久久久久久久久久久久冷 | 欧美亚洲一区二区三区 | 国产精品一区二区三区免费 | 国产精品久久久久久久一区探花 | 国产精品一级大片 | 亚洲天堂中文字幕在线观看 | 日韩中文字幕电影 | 可以在线观看的av网站 | 久久久www成人免费精品 | 狠狠草视频 | 欧美成人第一页 | 久久一区 | 久久亚洲综合 |