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

嵌套事務、掛起事務,Spring 是怎樣給事務又實現傳播特性的?

開發 后端
Spring 做為風靡世界的Java 開源框架,發揮著舉足輕重的作用。那你有沒有想過, Spring 內部又是怎么樣實現的事務呢?

[[334020]]

Spring 做為風靡世界的Java 開源框架,發揮著舉足輕重的作用。那你有沒有想過, Spring 內部又是怎么樣實現的事務呢?

而且 在 Spring 之中除了設置事務的「隔離級別」之外,還可以額外配置事務的「傳播特性」。你要知道,傳播特性里,有兩個家伙比較特別,一個PROPAGATION_REQUIRES_NEW ,還有一個是PROPAGATION_NESTED。你要知道,所謂的 REQUIRES_NEW,是會在方法級聯調用的時候,會開啟一個新的事務,同時掛起(suspend)當前事務;NESTED 代表的嵌套事務,則是在方法級聯調用的時候,在嵌套事務內執行。

我們應該都知道,這些傳播行為,是 Spring 獨有的,和數據庫沒有一毛錢關系。那在底層 Spring 用了什么黑魔法嗎?是怎么樣做到掛起事務的,又是怎么樣嵌套事務的呢?

咱們一起來揭秘。

毋庸置疑,數據的操作中,我們離不開事務。

銀行的轉帳操作中,我們相信如果一邊扣款,那對方一定會收到,而不竹籃打水一場空

事務在很多場景中都發揮著關鍵作用。

咱們先以 MySQL 為例,來捋一捋數據庫的事務,隔離級別。

然后再來看這些數據庫的配置,特性,在 Spring 里是怎樣做的事務對應的。

以及 Spring 所謂的傳播特性,又是如何作用到數據庫的事務的,怎樣做到掛起事務,嵌套事務。

事務

事務是什么?

它是一級原子性的SQL操作,一個獨立的工作單元。如果工作單元中的SQL語句執行成功,那會全部成功,一個失敗就會全部回滾。

與數據庫的事務同時為大眾熟知的是ACID。即數據庫的原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)。就像應用內為了線程之間的互斥,線程安全等,需要做大量的工作,數據庫為了 ACID,也做了許多的工作。

隔離級別

SQL 的標準中定義了四種隔離級別,規定了哪些是事務之間可見的,哪些是事務內可見的。

READ UNCOMMITTED (未提交讀) --> 兩個事務間,一個的事務還沒提交,但被另一個看到了。

READ COMMITTED (提交讀) --> 兩個事務間,只有一個事務提交之后,另一個事務才能看到。

REPEATABLE READ (可重復讀)--> 一個事務執行中,多次讀到的結果是一樣的,即使其他事務做了修改,也先「看不見」

SERIALIZABLE (可串行化)--> 最高隔離級別,強制事務串行執行。

由于這些隔離級別,會造成所謂的「臟讀」、「幻讀」、「不可重復讀」等問題,所以需要根據具體的場景選擇適用的。

如何設置隔離級別

對于 MySQL 的隔離級別,可以全局的,也可以設置 Session 級別的。

官方文檔設置語法如下:

 

我們通過客戶端連接到 MySQL Server 的時候,可以做一些配置,通過jdbc的 URL 你也能看的出來,這樣設置的就是 Session 級別的。

參考上面的官方文檔,設置 session 隔離級別的命令是它:

  1. set session transaction isolation level SERIALIZABLE

注意,MySQL 默認的隔離級別是 REPEATABLE READ,我的改過。同時,這里查詢當前隔離級別的SQL,舊版本的是SELECT @@TX_ISOLATION;,新版本的是SELECT @@Transaction_ISOLATION; 注意區分。

 

Spring 事務又是怎么回事

看過了數據庫的隔離級別之后,我們再來看 Spring 里的實現。

在 Spring 里,隔離級別的定義有五種,四個和數據庫的一致,另外包含一個 DEFAULT,代表不具體設置,直接使用數據庫定義的。

咱們看到數據庫的隔離級別可以設置 GLOBAL 級別的,也可以設置 SESSION 級別的,每個 SESSION 則代表的是一個連接。而在Spring 內,我們又是通過一個個獨立的「連接」來操作數據庫,完成CRUD。到這兒咱們應該就能知道,在 Spring 層面的設置,是通過 session 級別的 隔離來設置的,從而和數據庫里事務隔離級別做了對應來實現。

那傳播特性又是怎么回事呢?既然數據庫并不直接支持這樣的特性,Spring 又根據不同的傳播特性要求,來迂回實現了。

總結起來,對于級聯操作中,如果是REQUIRED_NEW這種的情況,所謂的掛起當前事務,開啟新的事務,是 Spring 又去申請了一個新的 Connection,這樣就會對應到一個新的事務上,然后將這個連接綁定到當前線程,再繼續執行;

對于嵌套事務,底層則是通過數據庫的 SAVEPOINT 來實現所謂的「子事務」

 

如果你熟悉代碼 DEBUG 過程中每個方法對應的 Frame,可以類比一下,如果執行失敗回滾的時候,可以指定回滾到當前事務的某個 SAVEPOINT,不需要全部回滾。

在 Spring 層面,是通過 JDBC 3.0來實現的,看下面這段代碼注釋。

  1. * <p>This transaction manager supports nested transactions via the JDBC 3.0 
  2. * {@link java.sql.Savepoint} mechanism. The 
  3. * {@link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults 
  4. to "true", since nested transactions will work without restrictions on JDBC 
  5. * drivers that support savepoints (such as the Oracle JDBC driver). 

事務掛起的部分代碼如下:

  1. /** 
  2.    * Suspend the given transaction. Suspends transaction synchronization first
  3.    * then delegates to the {@code doSuspend} template method. 
  4.    * @param transaction the current transaction object 
  5.    * (or {@code nullto just suspend active synchronizations, if any
  6.    * @return an object that holds suspended resources 
  7.    * (or {@code null} if neither transaction nor synchronization active) 
  8.    * @see #doSuspend 
  9.    * @see #resume 
  10.    */ 
  11.   @Nullable 
  12.   protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException { 
  13.     if (TransactionSynchronizationManager.isSynchronizationActive()) { 
  14.       List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization(); 
  15.       try { 
  16.         Object suspendedResources = null
  17.         if (transaction != null) { 
  18.           suspendedResources = doSuspend(transaction); 
  19.         } 
  20.         String name = TransactionSynchronizationManager.getCurrentTransactionName(); 
  21.         TransactionSynchronizationManager.setCurrentTransactionName(null); 
  22.         boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); 
  23.         TransactionSynchronizationManager.setCurrentTransactionReadOnly(false); 
  24.         Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); 
  25.         TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null); 
  26.         boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive(); 
  27.         TransactionSynchronizationManager.setActualTransactionActive(false); 
  28.         return new SuspendedResourcesHolder( 
  29.             suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive); 
  30.       } 
  31.   } 

邏輯在 doSuspend里,繼續看

  1. @Override 
  2.   protected Object doSuspend(Object transaction) { 
  3.     DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction
  4.     txObject.setConnectionHolder(null); 
  5.     return TransactionSynchronizationManager.unbindResource(obtainDataSource()); 
  6.   } 
  7.  
  8.   @Override 
  9.   protected void doResume(@Nullable Object transaction, Object suspendedResources) { 
  10.     TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources); 
  11.   } 

然后對應的bind 和 unbind 操作,是在ThreadLocal 對象里,將資源對象綁定或移出當前線程對應的 resources 來實現的。

  1. private static final ThreadLocal<Map<Object, Object>> resources = 
  2.       new NamedThreadLocal<>("Transactional resources"); 
  3. /** 
  4.    * Bind the given resource for the given key to the current thread. 
  5.    * @param key the key to bind the value to (usually the resource factory) 
  6.    * @param value the value to bind (usually the active resource object) 
  7.    * @throws IllegalStateException if there is already a value bound to the thread 
  8.    * @see ResourceTransactionManager#getResourceFactory() 
  9.    */ 
  10.   public static void bindResource(Object key, Object value) throws IllegalStateException { 
  11.     Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); 
  12.     Assert.notNull(value, "Value must not be null"); 
  13.     Map<Object, Object> map = resources.get(); 
  14.     // set ThreadLocal Map if none found 
  15.     if (map == null) { 
  16.       map = new HashMap<>(); 
  17.       resources.set(map); 
  18.     } 
  19.     Object oldValue = map.put(actualKey, value); 
  20.     // Transparently suppress a ResourceHolder that was marked as void... 
  21.     if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) { 
  22.       oldValue = null
  23.     } 
  24.   } 

對比上面的說明和代碼,這兩個傳播特性的區別也很明了了:

NESTED 的特性,本質上還是同一個事務的不同保存點,如果涉及到外層事務回滾,則內層的也將會被回滾;

 

REQUIRED_NEW 的實現對應的是一個新的事務,拿到的是新的資源,所以外層事務回滾時,不影響內層事務。

本文轉載自微信公眾號「Tomcat那些事兒」,可以通過以下二維碼關注。轉載本文請聯系Tomcat那些事兒公眾號。

 

 

責任編輯:武曉燕 來源: Tomcat那些事兒
相關推薦

2023-10-30 07:36:19

Spring事務傳播機制

2024-12-17 16:26:31

2024-04-17 08:11:01

數據庫事務流程

2022-08-27 14:14:06

Spring事務開發

2024-01-04 12:48:00

Spring

2020-08-19 09:45:29

Spring數據庫代碼

2021-09-02 18:39:01

Spring隔離級別

2023-11-02 07:52:30

Java工具

2009-12-22 15:55:10

WCF事務

2009-07-20 18:11:52

iBATIS事務Spring

2023-05-06 07:29:49

Spring事務傳播

2017-01-19 15:32:36

Java全局事務本地事務

2024-12-17 16:44:22

Spring開發

2022-09-27 21:14:54

Spring事務傳播機制

2009-06-22 09:01:57

Spring聲明式事務

2022-04-26 21:49:55

Spring事務數據庫

2022-10-08 00:24:40

嵌套事務加入事務事務

2009-06-30 16:41:12

Hibernate的事

2018-11-16 15:35:10

Spring事務Java

2018-07-17 10:58:45

數據庫數據庫事務隔離級別
點贊
收藏

51CTO技術棧公眾號

91久久精品美女| 91麻豆国产自产在线观看| 久久只精品国产| 日本国产精品视频| 在线观看亚洲网站| 激情小说亚洲图片| 欧美日韩一卡二卡三卡| 日本久久久网站| 国产在线一在线二| 国产成人午夜99999| 国产做受高潮69| 免费看一级黄色| 欧美尿孔扩张虐视频| 欧美精选一区二区| 人妻熟女一二三区夜夜爱| 50度灰在线| 国产欧美综合色| 国产日韩欧美综合精品| 国产尤物在线观看| 免费永久网站黄欧美| 久久99久国产精品黄毛片入口| 在线 丝袜 欧美 日韩 制服| 国产午夜久久av| 日本道精品一区二区三区| 欧美a级免费视频| 95在线视频| 久久尤物电影视频在线观看| 成人av影视在线| 11024精品一区二区三区日韩| 国产精品久久久久9999高清| 色综合视频一区中文字幕| 女人十八毛片嫩草av| 亚洲精华一区二区三区| 精品国产精品一区二区夜夜嗨| 超碰在线人人爱| 涩涩网在线视频| 亚洲成av人片在线| 欧美黄色免费网址| 色女人在线视频| 亚洲视频一二三| 亚洲一区二区三区欧美| 爱爱爱免费视频在线观看| 久久人人超碰精品| 九九九九九精品| 亚洲国产999| 国产大片一区二区| 亚洲一区中文字幕在线观看| 国产又色又爽又黄又免费| 日本va欧美va精品发布| 538国产精品一区二区在线| 国产一级淫片免费| 亚洲网站啪啪| 欧美精品videos| 国产在线视频卡一卡二| 国语对白精品一区二区| 欧美激情第三页| 久久精品美女视频| 999在线观看精品免费不卡网站| 欧美激情在线观看| 日韩精品国产一区二区| 日韩视频一区| 日本精品久久久久久久| 蜜臀尤物一区二区三区直播| 日本欧洲一区二区| 国产日韩在线亚洲字幕中文| 一级黄色片在线观看| 国产在线精品一区二区三区不卡 | 欧美国产日韩综合| 欧美在线三区| 欧美精品激情视频| 国产精品自拍99| 天堂av在线一区| 91精品久久久久久久久久入口| 国产一区二区三区四区视频| 国产一区二区伦理片| 国产91视觉| 免费资源在线观看| 国产精品第13页| 欧美性猛交内射兽交老熟妇| 久久久男人天堂| 在线视频国内自拍亚洲视频| 国产成年人视频网站| 日韩中文字幕| 亚洲色图第一页| 亚洲熟女毛茸茸| 亚洲经典在线| 国产精品视频在线观看| 国产av无码专区亚洲av麻豆| 99久久精品99国产精品| 性欧美videosex高清少妇| 国产精品久久久久久福利| 亚洲h精品动漫在线观看| 久草在在线视频| 欧美a级大片在线| 亚洲精品天天看| 成人免费视频网站入口::| 中日韩男男gay无套| 成人黄色在线观看| 男生女生差差差的视频在线观看| 综合久久久久久| 国产视频九色蝌蚪| 不卡精品视频| 精品无人国产偷自产在线| 韩国一级黄色录像| 免费视频久久| 成人欧美一区二区三区视频| 国产爆初菊在线观看免费视频网站 | 18+激情视频在线| 色欧美88888久久久久久影院| 日韩av福利在线观看| 国产成人精品999在线观看| 欧美激情极品视频| 在线视频1卡二卡三卡| 91原创在线视频| 97久久国产亚洲精品超碰热| 国产精品久久久久久吹潮| 日韩av在线免费| 青青草原免费观看| 麻豆传媒一区二区三区| 欧美最大成人综合网| 暧暧视频在线免费观看| 51久久夜色精品国产麻豆| 久久久久久久久久久久| 最新日韩在线| av一区二区三区免费| 免费网站成人| 欧美日韩国产中文| 免费黄在线观看| 久久午夜视频| 美乳视频一区二区| 天堂资源在线| 亚洲精品国产精品国产自| 久久久久久久福利| 国产精品99久久久久久似苏梦涵| 亚洲精品乱码久久久久久蜜桃91 | 少妇一级淫片免费放播放| 伊人情人综合网| 成人精品久久久| 成人动漫在线免费观看| 91豆麻精品91久久久久久| 亚洲av网址在线| 一区二区三区四区五区在线| 久久99欧美| 忘忧草在线影院两性视频| 精品福利av导航| 国产精品.www| 99精品欧美一区二区三区综合在线| 国产无限制自拍| 欧美精品中文| 国产成人精品视频| 国产一级片在线播放| 在线观看亚洲a| 精品无码在线观看| 精品一区二区三区在线观看| 国产对白在线播放| 日韩成人在线观看视频| 欧美激情二区三区| 外国精品视频在线观看| 一本到三区不卡视频| av黄色在线免费观看| 日本aⅴ亚洲精品中文乱码| 亚洲一区尤物| 日韩成人18| 亚洲97在线观看| 看电影就来5566av视频在线播放| 在线观看国产精品网站| fc2ppv在线播放| 成人自拍视频在线| 自拍日韩亚洲一区在线| 黑人操亚洲人| 91美女福利视频高清| 国产黄色大片在线观看| 亚洲欧美日韩区| 一级片在线观看视频| 一区二区三区四区中文字幕| 插我舔内射18免费视频| 久久综合导航| 欧美大片免费播放| 欧美sss在线视频| 国产精品9999| 羞羞的视频在线看| 亚洲欧美成人精品| 国产精品无码白浆高潮| 婷婷开心久久网| 欧美xxxx精品| www.在线欧美| 在线免费观看视频黄| 国产真实久久| 亚洲激情啪啪| 卡一精品卡二卡三网站乱码| 国产精品午夜一区二区欲梦| 国产在线xxx| 在线观看日韩视频| 蜜桃91麻豆精品一二三区| 在线一区二区三区| 不卡的免费av| 国产精品久久毛片a| 欧美精品欧美极品欧美激情| 精品亚洲aⅴ乱码一区二区三区| 无码人妻少妇伦在线电影| 不卡在线一区| 久久狠狠久久综合桃花| 玖玖精品一区| 国产精品一二三在线| 2021中文字幕在线| 久久精品欧美视频| 精品一二三区视频| 亚洲成人精品久久久| 888奇米影视| 91国偷自产一区二区三区成为亚洲经典| 国产一区二区三区在线视频观看| 久久久久久久免费视频了| 亚洲免费观看在线| 精品中文av资源站在线观看| 午夜肉伦伦影院| 在线欧美视频| 亚洲天堂第一区| 久久国产精品亚洲人一区二区三区| 国产私拍一区| 综合激情久久| 91亚洲精品久久久| 亚洲电影二区| 国产精品久久久久久久久久免费 | 精品国产乱码久久久久久图片| 在线视频播放大全| 欧美特级限制片免费在线观看| 天天操天天摸天天干| 亚洲午夜精品17c| 特级片在线观看| 亚洲精品国产无套在线观 | 精品人伦一区二区三区蜜桃网站| 欧美毛片在线观看| 亚洲精品欧美专区| 亚洲一级生活片| 亚洲图片你懂的| 无码黑人精品一区二区| 亚洲欧洲精品一区二区三区| 香蕉成人在线视频| 国产精品天美传媒沈樵| 久久久久久久久久久久| 欧美国产日产图区| 中文字幕第二区| 国产精品久久久久四虎| 香蕉成人在线视频| 综合色中文字幕| 特级片在线观看| 亚洲电影激情视频网站| 精品成人免费视频| 精品日韩中文字幕| 日本免费精品视频| 欧美色窝79yyyycom| 亚洲天堂男人网| 91精品国产aⅴ一区二区| 国产精品欧美亚洲| 精品少妇一区二区三区日产乱码| 亚洲成人第一区| 亚洲国产精品视频在线观看| 欧美新色视频| 色小说视频一区| 超碰免费在线播放| 97人人做人人爱| 日韩久久一区二区三区| 国产免费成人av| 亚洲天堂中文字幕在线观看| 狠狠色噜噜狠狠狠狠色吗综合| 亚洲视频分类| 亚洲一区二区三区午夜| 欧美福利视频| 69堂免费视频| 七七婷婷婷婷精品国产| 在线观看网站黄| 99视频一区二区| 微拍福利一区二区| 亚洲欧美日韩系列| 国产在线观看黄色| 欧美日本一区二区| 人妻一区二区三区四区| 亚洲视频在线视频| av黄在线观看| 欧美专区第一页| 亚洲资源在线| 免费在线成人av电影| 五月天久久网站| 自慰无码一区二区三区| 久久国产麻豆精品| 天天插天天射天天干| 国产精品福利影院| 黄色片视频网站| 欧美乱妇23p| 五月天婷婷在线播放| 久久精品视频在线| 樱花草涩涩www在线播放| 91欧美精品午夜性色福利在线| 久久亚州av| 国产树林野战在线播放| 久久综合导航| 久久久午夜精品福利内容| 国产精品三级视频| 国产成人免费看| 欧美一区二区在线看| 国自产拍在线网站网址视频| 欧美第一黄色网| 日本免费在线一区| 欧美三级华人主播| 欧美午夜影院| 亚洲一区精品视频在线观看| 久久久精品国产免大香伊| 黄色一级视频免费| 欧美久久久久久久久久| 免费在线超碰| 久久99精品久久久久久噜噜| 国产亚洲人成a在线v网站| 免费精品视频一区二区三区| 欧美区一区二| 午夜天堂在线视频| 国产日韩欧美综合一区| 国产三级av片| 欧美精品一区二区三区蜜桃视频| 国产写真视频在线观看| 国产精品男人的天堂| 九九免费精品视频在线观看| 九九热只有这里有精品| 国产精品一区久久久久| 久久精品在线观看视频| 欧美最新大片在线看| 日韩av免费观影| 性色av一区二区三区免费| 99a精品视频在线观看| 国产精品免费看久久久无码| 国产精品中文字幕日韩精品| 婷婷激情四射网| 884aa四虎影成人精品一区| 99免在线观看免费视频高清| 国产成人福利视频| 国产欧美日韩精品一区二区免费| 国产真实乱子伦| www国产成人免费观看视频 深夜成人网| 日本三级中文字幕| 亚洲第一页在线| 精精国产xxxx视频在线野外| 国产精品一级久久久| 亚洲欧洲日本一区二区三区| 催眠调教后宫乱淫校园| 五月天视频一区| 日韩资源在线| 国产999精品视频| 欧美一区电影| 在线能看的av网站| 亚洲人成在线观看一区二区| 国产黄a三级三级三级| 欧美日韩xxxxx| 精品三级av在线导航| 日韩欧美一区二| 久久久久国色av免费看影院| 亚洲精品毛片一区二区三区| 中文字幕在线精品| www久久久| 91精品国产91久久久久麻豆 主演| bt7086福利一区国产| 日韩在线播放中文字幕| 在线播放精品一区二区三区| 9999精品| 久久综合色视频| 国产欧美日本一区视频| 国产乱码久久久| 国内精品400部情侣激情| 免费一区二区| 中文av字幕在线观看| 亚洲综合在线观看视频| 神马亚洲视频| 国产自摸综合网| 亚洲天堂偷拍| 中文字幕伦理片| 欧美va亚洲va| 桃色一区二区| 99re6这里有精品热视频| 91小视频在线观看| 亚洲永久精品视频| 欧美精品www| 北条麻妃国产九九九精品小说| 久久久精品视频国产| 疯狂蹂躏欧美一区二区精品| 18视频免费网址在线观看| 国产二区一区| 日本一区中文字幕| 欧美一级高潮片| 在线一区二区日韩| 国产一区二区在线视频你懂的| 久久午夜夜伦鲁鲁一区二区| 亚洲综合免费观看高清在线观看 | 日韩在线观看免费高清完整版| 懂色av一区二区| 中文字幕永久有效| 欧美日韩一区二区精品| 免费大片在线观看www| 蜜桃导航-精品导航| 国产91富婆露脸刺激对白| 国产偷人爽久久久久久老妇app | 久久夜色精品国产噜噜亚洲av| 久久综合88中文色鬼|