精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

詳解Spring多線程下如何保證事務的一致性

開發 前端
我們先來大概的了解下Spring事務的工作原理,核心技術是通過AOP實現,將獲取的Connection對象綁定到當前線程上下文中(ThreadLocal)。

環境:Spring5.3.23

1. 事務原理

首先,我們先來大概的了解下Spring事務的工作原理,核心技術是通過AOP實現,將獲取的Connection對象綁定到當前線程上下文中(ThreadLocal)。

事務核心攔截器TransactionInterceptor對象,如下(以下只會列出核心代碼):

public class TransactionInterceptor {
  public Object invoke(MethodInvocation invocation) {
    // 該方法調用為核心方法,該方法在父類中
    return invokeWithinTransaction(...) ;
  }
}

父類TransactionAspectSupport

public abstract class TransactionAspectSupport {
  protected Object invokeWithinTransaction(...) {
    // 1.1.創建事務對象
    TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
    try {
        // 調用下一個攔截器或者是目標方法
      retVal = invocation.proceedWithInvocation();
    }
    catch (Throwable ex) {
      // 1.2.回滾事務
      completeTransactionAfterThrowing(txInfo, ex);
      throw ex;
    } finally {
      // 重置ThreadLocal中的TransactionInfo對象
      cleanupTransactionInfo(txInfo);
    }
    // 1.3.提交或者回滾事務
    commitTransactionAfterReturning(txInfo);
    return retVal;
  }  
}

上面代碼列出了主要的事務執行流程及動作,我們主要是關心數據庫連接對象Connection在當前線程中是如何使用的。

創建事務對象

protected TransactionInfo createTransactionIfNecessary(
    @Nullable PlatformTransactionManager tm,
    @Nullable TransactionAttribute txAttr, 
    final String joinpointIdentification) {
  TransactionStatus status = null;
  if (txAttr != null) {
    if (tm != null) {
      // 創建事務狀態對象
      status = tm.getTransaction(txAttr);
    }
  }
  // 將事務狀態對象包裝到TransactionInfo中,然后將這個對象綁定到當前線程中
  return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

創建事務狀態對象

public abstract class AbstractPlatformTransactionManager {
  public final TransactionStatus getTransaction(...) {
    if (isExistingTransaction(transaction)) {
      // Existing transaction found -> check propagation behavior to find out how to behave.
      return handleExistingTransaction(def, transaction, debugEnabled);
    }


    // 如果超時時間 < -1則拋出異常
    if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
      throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
    }


    // 當前不存在事務,則拋出異常
    if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
      throw new IllegalTransactionStateException(
          "No existing transaction found for transaction marked with propagation 'mandatory'");
    }
    // 其它的傳播特性,開啟事務功能
    else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
        def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
        def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
      try {
        // 開始事務
        return startTransaction(def, transaction, debugEnabled, suspendedResources);
      }
    }
  }
}

開始事務

private TransactionStatus startTransaction(
    TransactionDefinition definition, 
    Object transaction,
    boolean debugEnabled, 
    @Nullable SuspendedResourcesHolder suspendedResources) {


  boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
  DefaultTransactionStatus status = newTransactionStatus(
      definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
  //     
  doBegin(transaction, definition);
  prepareSynchronization(status, definition);
  return status;
}

創建Connection對象,并綁定到當前線程

public class DataSourceTransactionManager {
  protected void doBegin(
      Object transaction, 
      TransactionDefinition definition) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    Connection con = null;
    try {
      if (!txObject.hasConnectionHolder() ||
          txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
        // 獲取數據庫連接對象  
        Connection newCon = obtainDataSource().getConnection();
        txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
      }
      // 將連接對象綁定到當前的線程
      if (txObject.isNewConnectionHolder()) {
        TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
      }
    }
  }
}

到此,已經清楚了當開始一個新的事務時,Spring會將獲取的Connection綁定到當前的Thread中。

當我們使用通過JdbcTemplate操作數據庫時,如下:

public class JdbcTemplate {
  // 核心執行方法
  private <T> T execute(...) {
    // 獲取數據庫連接對象
    Connection con = DataSourceUtils.getConnection(obtainDataSource());
  }
}

DataSourceUtils

public abstract class DataSourceUtils {
  public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
    try {
      return doGetConnection(dataSource) ;
    }
  }
  public static Connection doGetConnection(DataSource dataSource) throws SQLException {
    // 通過TransactionSynchronizationManager從當前線程上下文中獲取連接對象
    // 在上面我們也是通過這個對象將連接對象綁定到當前的Thread中
    ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
    if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
      conHolder.requested() ;
      if (!conHolder.hasConnection()) {
        conHolder.setConnection(fetchConnection(dataSource)) ;
      }
      return conHolder.getConnection() ;
    }
  }
}

原理相信你應該非常清楚了,每個線程都會綁定自己的Connection。那在多線程下每個線程都使用的是自己的Connection對象,所以要想保證事務的一致性,單靠傳統的方式一個@Transaction是肯定無法解決的,接下來我們就來實現一個多線程下的事務一致性的處理。

2.多線程事務

多線程下要實現事務的一致性,我們需要借助JUC下的相關類來實現。

這里直接給出代碼示例:

static class PersonService {
  @Resource
  private JdbcTemplate jdbcTemplate;
  @Resource
  private DataSource dataSource ; 


  @Transactional
  public void save() throws Exception {
    CountDownLatch cdl = new CountDownLatch(2) ;
    AtomicBoolean txRollback = new AtomicBoolean(false) ;
    CompletableFuture.runAsync(() -> {
      Person person = new Person();
      person.setAge(1);
      person.setName("張三");
      transactionTemplate.execute(status -> {
        int result = 0 ;
        try {
          result = jdbcTemplate.update("insert into t_person (age, name) values (?, ?)", person.getAge(), person.getName()) ;
          // TODO
          // System.out.println(1 / 0) ;
        } catch (Exception e) {
            // 當發生異常后將狀態該為true
          txRollback.set(true) ;
        }
        try {
            // 計數減一
          cdl.countDown() ;
          // 繼續等待其它線程結束
          cdl.await() ;
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
          // 如果回滾狀態為true說明有線程發生了異常,需要事務回滾
        if (txRollback.get()) {
          // 標記當前事務回滾
          status.setRollbackOnly() ;
        }
        System.out.printf("%s Insert Operator Result: %d 次%n", Thread.currentThread().getName(), result);
        return result ;
      }) ;
      }) ;
    transactionTemplate.execute(status -> {
      Person person = new Person();
      person.setAge(2);
      person.setName("李四");
      int result = 0 ;
      try {
        result = jdbcTemplate.update("insert into t_person (age, name) values (?, ?)", person.getAge(), person.getName()) ;
        // TODO
        TimeUnit.SECONDS.sleep(3) ;
      } catch (Exception e) {
        txRollback.set(true) ; 
      }
      try {
        cdl.countDown() ;
        cdl.await() ;
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      if (txRollback.get()) {
        // 回滾
        status.setRollbackOnly() ;
      }
      System.out.printf("%s Insert Operator Result: %d 次%n", Thread.currentThread().getName(), result);
      return result ;
    }) ;
    cdl.await() ;
    System.err.println("Operator Complete...") ;
  }
}

以上就是借助JUC來實現多線程下的事務一致性問題。

其實如果你真的理解了事務的原理,其實這里還有更加簡單的實現方式,大家可以先思考,咱們下期再說這種簡單的實現方法。

完畢!!!

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2021-03-04 06:49:53

RocketMQ事務

2022-10-19 12:22:53

并發扣款一致性

2020-01-02 09:06:23

微服務數據框架

2025-02-10 03:00:00

2022-08-29 08:38:00

事務一致性

2019-08-30 12:46:10

并發扣款查詢SQL

2020-08-05 08:46:10

NFS網絡文件系統

2025-03-27 08:20:54

2024-01-10 08:01:55

高并發場景悲觀鎖

2024-12-26 15:01:29

2023-09-07 08:11:24

Redis管道機制

2020-04-01 15:50:17

TiDBMySQL數據庫

2020-06-01 22:09:48

緩存緩存同步緩存誤用

2021-07-21 15:50:42

Serverless 業務部署

2021-12-14 07:15:57

MySQLRedis數據

2024-08-20 16:13:52

2023-05-26 07:34:50

RedisMySQL緩存

2024-10-28 12:41:25

2024-01-15 10:38:20

多級緩存數據一致性分布式緩存

2022-03-29 10:39:10

緩存數據庫數據
點贊
收藏

51CTO技術棧公眾號

欧美日韩成人一区二区| 精品在线一区二区| 日韩精品高清在线| 日本女优一区| 91在线播放网址| 人人澡人人澡人人看欧美| b站大片免费直播| 国产精品美女午夜爽爽| 一区二区三区加勒比av| 精品无人乱码一区二区三区的优势| 中文字幕一区在线播放| 一区二区三区在线电影| 日韩精品视频免费| 欧美一级xxxx| 韩日毛片在线观看| 国产精品嫩草99a| 精品视频高清无人区区二区三区| 在线观看毛片av| 亚洲人成人一区二区三区| 中文字幕最新精品| 亚洲图片综合网| 亚洲精品第一| 欧美日韩在线影院| 欧美与动交zoz0z| 久久国产精品高清一区二区三区| 国产成人综合在线| 国产精品久久久久久久电影| 好吊妞视频一区二区三区| 日韩在线高清| 亚洲精品色婷婷福利天堂| 天天久久综合网| 外国电影一区二区| 精品福利在线视频| 成人免费a级片| 幼a在线观看| 久久嫩草精品久久久精品| 99久久国产免费免费| 一级黄色录像大片| 国产视频一区欧美| 久久久久免费视频| 欧美性受xxxx黑人| 亚洲宅男一区| 日韩成人高清在线| 亚洲av人人澡人人爽人人夜夜| 欧美视频精品| 欧美日韩亚洲另类| 免费在线观看毛片网站| 久草在线视频资源| 亚洲日本韩国一区| 国产又黄又爽免费视频| av大片在线播放| 国产亚洲美州欧州综合国| 精品无人区一区二区三区| 亚洲第一色网站| 国产一区中文字幕| 亚洲一区二区三区乱码aⅴ| 国产一区二区三区在线观看| 蜜桃视频一区二区| 国产精品青青在线观看爽香蕉 | 中文字幕码精品视频网站| 麻豆成人精品| 国产成人精品午夜| 国产精品午夜一区二区| 日韩精品福利网| 国产精品久久久久久中文字| 亚洲天堂视频在线播放| 蜜桃av一区二区| 91免费看片网站| 国产一级片自拍| 99只有精品| 欧美久久一区二区| 性鲍视频在线观看| 51vv免费精品视频一区二区| 精品福利一二区| 中文字幕在线永久| 亚洲三级精品| 尤物九九久久国产精品的分类| 娇妻被老王脔到高潮失禁视频| 日韩成人免费| 欧美大尺度激情区在线播放| 五月天丁香激情| 夜夜精品视频| 国产精品成久久久久三级| 一二三四区在线| 国产成人在线视频免费播放| 国产精品久久久一区二区三区| 神马午夜一区二区| 91色porny在线视频| 日韩中文不卡| 在线看福利影| 欧美性感美女h网站在线观看免费| 国产无套粉嫩白浆内谢的出处| japansex久久高清精品| 精品免费一区二区三区| 男人操女人动态图| 91精品一区二区三区综合| 韩日欧美一区二区| 自拍偷拍福利视频| 高清国产一区二区| 日本午夜精品一区二区三区| 18+视频在线观看| 粉嫩av一区二区三区免费野| 亚洲欧美国产中文| 免费日韩一区二区三区| 精品国产一区二区三区久久狼黑人| 国产一级做a爰片在线看免费| 国产一区二区小视频| 免费人成在线不卡| 成人性色av| 国产精品久久久久一区二区国产| 亚洲欧美一区二区三区久本道91| 国产高清精品在线观看| 成人精品在线| 亚洲欧美综合精品久久成人| 唐朝av高清盛宴| 日本不卡在线视频| 九九九九九精品| 九七久久人人| 色94色欧美sute亚洲线路一ni | 国产成人一区在线| 色播亚洲婷婷| 国产伦子伦对白在线播放观看| 91精品国产福利在线观看| 亚洲av成人无码久久精品| 亚洲精品综合| 亚洲aⅴ男人的天堂在线观看| 国产私拍精品| 欧美日韩色婷婷| 国产亚洲精品成人a| 欧洲精品一区二区三区| 亚洲国产精品系列| 欧美成人三级视频| 久久99热国产| 亚洲精品中字| 日本一区二区三区视频在线| 日韩精品视频三区| 久久综合色综合| 国产一区激情在线| 一本色道久久综合亚洲精品婷婷| **在线精品| 亚洲欧美国产精品久久久久久久 | 黄色免费在线看| 欧美三级韩国三级日本三斤| 国产精品原创| 99精品国产热久久91蜜凸| 久久久无码中文字幕久...| 亚洲第一会所001| 亚洲欧美中文字幕在线一区| 天天干天天干天天干天天| av一区二区不卡| 妞干网视频在线观看| 中文字字幕码一二三区| 欧美高清在线| 国产欧美精品一区二区三区-老狼 国产欧美精品一区二区三区介绍 国产欧美精品一区二区 | 欧美顶级大胆免费视频| 久久久久亚洲精品| 人妻91麻豆一区二区三区| 亚洲精品成a人| 日本黄色www| 国产精品chinese| 成人在线免费观看一区| segui88久久综合| 精品国产乱码久久久久久1区2区| 国产在线免费视频| 99亚偷拍自图区亚洲| 又粗又黑又大的吊av| 亚洲国产合集| 国产精品免费视频xxxx| 香蕉视频国产在线观看| 91精品国产一区二区人妖| 日本黄色小说视频| 成人激情综合网站| 国产91对白刺激露脸在线观看| 杨幂一区二区三区免费看视频| 国产高清视频一区三区| 毛片在线看网站| 日韩视频不卡中文| 91精品国产乱码在线观看| 91天堂素人约啪| 玩弄japan白嫩少妇hd| 成人精品中文字幕| 51国偷自产一区二区三区的来源| 91福利区在线观看| 一区二区欧美激情| aaaa一级片| 懂色aⅴ精品一区二区三区蜜月| 国产亚洲精品熟女国产成人| 国产毛片精品视频| 国产人妻777人伦精品hd| 精品国产网站| 成人av网站观看| 亚洲第一影院| 欧美美最猛性xxxxxx| 你懂得网站在线| 91精品国产色综合久久ai换脸| 日本三级免费看| 国产精品欧美极品| 亚洲精品激情视频| 麻豆国产精品一区二区三区| 亚洲色成人www永久在线观看| 精品国产一区二区三区久久久蜜臀 | 成人美女视频在线看| 亚洲欧美激情网| 日韩欧美成人免费视频| 六十路精品视频| 日韩欧美三区| 777国产偷窥盗摄精品视频| av男人的天堂在线| 亚洲精品一区二区三区四区高清 | www黄色网址| 日韩国产高清影视| 国产欧美123| 精品国产乱码久久久久久蜜坠欲下 | 永久免费网站视频在线观看| 国产剧情一区| 精品乱码一区二区三区| 精品国产亚洲一区二区三区在线| 欧美最猛性xxxxx亚洲精品| 怡红院av在线| www.xxxx精品| a√资源在线| 日韩电影免费观看中文字幕| hs视频在线观看| 欧美狂野另类xxxxoooo| 自拍偷拍校园春色| 激情亚洲一区二区三区四区| 国产女人被狂躁到高潮小说| 日本一区二区三区高清不卡 | 国产第一页在线播放| 国产精品久久久久久久久免费丝袜 | 国产91ⅴ在线精品免费观看| 国产丝袜高跟一区| 午夜精品久久久久久久99| 欧美精品乱码久久久久久| 91国产丝袜播放在线| 亚洲人成网站色在线观看| 欧美人与禽zoz0善交| 91丨九色porny丨蝌蚪| 真实乱偷全部视频| 麻豆精品精品国产自在97香蕉| 国产极品美女高潮无套久久久| 欧美精品一级| 欧美性受黑人性爽| 日韩av在线播放网址| 亚洲精品一区国产精品| 国产尤物久久久| 久久综合精品一区| 最新亚洲精品| 免费av一区二区三区| 久久夜色精品国产噜噜av小说| 91精品黄色| 疯狂欧洲av久久成人av电影| 日韩av成人在线| 九九九伊在线综合永久| 国产91色在线| 成人在线爆射| 国产精品自在线| 巨大黑人极品videos精品| 97在线观看视频| 欧美成人影院| 视频精品一区| 日韩美女视频免费看| 小早川怜子影音先锋在线观看| 欧美精品在线网站| 亚洲看片网站| 亚洲aa在线| 国产视频一区二区三区四区| 国产精品色在线网站| 国产欧美在线一区二区| 久久动漫网址| 亚洲国产精品久久久久久女王| 国产一区二区三区日韩精品| 日韩av电影免费在线观看| 国产精品99一区二区三区| 欧美精品久久96人妻无码| 91精品国产91久久综合| 91动漫在线看| 亚洲欧美日韩综合国产aⅴ| 少妇大叫太大太粗太爽了a片小说| 亚洲成人中文| 91视频免费网站| 成人免费91| 免费日韩av电影| 国产videos久久| 亚洲视频电影| 一二三区精品| 国产情侣av自拍| 久久99久久久久| 五十路六十路七十路熟婆| 久久久99精品免费观看| 在线观看黄网址| 福利微拍一区二区| 在线观看日韩一区二区| 欧美一级黄色录像| 国产免费永久在线观看| 欧美成人午夜剧场免费观看| 白浆视频在线观看| 久久艹精品视频| 国产一区91| 欧美成人黑人猛交| 国产激情偷乱视频一区二区三区| 一级淫片在线观看| 粉嫩av一区二区三区在线播放| 性高潮久久久久久久| 久久女同性恋中文字幕| 亚洲欧美精品aaaaaa片| 一级女性全黄久久生活片免费| 中文字幕一区在线播放| 欧美xxxx性| 国产精品日韩一区二区免费视频| 精品久久对白| 青青草综合视频| 亚洲视频在线观看免费视频| 懂色av一区二区三区蜜臀 | 免费一二一二在线视频| 国产精品久久久久久久久免费看| 国产区精品视频在线观看豆花| 日韩资源av在线| 欧美激情五月| 九九九在线观看视频| 成人av电影在线网| 黄色录像一级片| 欧美撒尿777hd撒尿| 熟妇人妻av无码一区二区三区| xvideos亚洲人网站| 成人国产激情| 久久96国产精品久久99软件| 欧美一区免费| 中文字幕一区二区在线观看视频| 久久久久久久久久电影| 91精品少妇一区二区三区蜜桃臀| 在线免费观看成人短视频| 精品手机在线视频| 亚洲h动漫在线| 成人午夜免费在线观看| 日韩在线观看免费| 日韩av超清在线观看| 欧美韩国日本精品一区二区三区| 欧美日韩国内| 手机看片一级片| 成人精品在线播放| 国产婷婷97碰碰久久人人蜜臀 | 日韩成人av在线播放| 影音先锋男人在线资源| 国产欧美一区二区| 蜜桃一区二区三区| 免费黄色福利视频| 99久久久国产精品| 中文字幕在线观看二区| 欧美日韩国产天堂| 国产乱视频在线观看| 国产精品成人av性教育| 日韩美女毛片| 日产精品久久久久久久蜜臀| 福利91精品一区二区三区| 成人涩涩小片视频日本| 欧美不卡视频一区| 美女尤物在线视频| 国产九色精品| 久久亚洲图片| 在线观看日本中文字幕| 欧美亚洲不卡| 不卡一区二区三区视频| 91欧美在线| 特级黄色片视频| 一区精品在线播放| 97人妻一区二区精品免费视频| 18禁网站免费无遮挡无码中文| 久久99蜜桃精品| 亚洲成人生活片| 91精品久久久久久蜜臀| 国产精品久久久久久福利| 亚洲最大的免费| 欧美一区免费| 手机在线观看日韩av| 亚洲综合一区在线| 丰满人妻一区二区三区免费视频| 欧美怡春院一区二区三区| 亚洲人成网www| 久久久一本二本三本| 国产日韩精品一区二区三区| 特大黑人娇小亚洲女mp4| 国产乱码精品一区二区三| 亚洲另类欧美日韩| 亚洲午夜av久久乱码| 你懂得影院夜精品a| 国产经典久久久| 99视频精品全部免费在线| 国产精品欧美综合| 久久久精品久久| 国产图片一区| 五月婷婷六月丁香激情| 中文字幕一区av| 网站黄在线观看| 国产精品久久激情| 四季av一区二区凹凸精品| 艳妇乳肉豪妇荡乳xxx| 色先锋资源久久综合| 2024最新电影免费在线观看 | 狠狠躁夜夜躁人人爽天天高潮|