日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

spring更新后 外层事务查不到_再深一点:面试工作两不误,源码级理解Spring事务...

發(fā)布時(shí)間:2024/7/23 javascript 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring更新后 外层事务查不到_再深一点:面试工作两不误,源码级理解Spring事务... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原創(chuàng):小姐姐味道(微信公眾號(hào)ID:xjjdog),歡迎分享,轉(zhuǎn)載請(qǐng)保留出處。

Spring有5種隔離級(jí)別,7種傳播行為。這是面試常問的內(nèi)容,也是代碼中經(jīng)常碰到的知識(shí)點(diǎn)。這些知識(shí)枯燥而且乏味,其中有些非常的繞。如果栽在這上面,就實(shí)在是太可惜了。

xjjdog在一些事務(wù)的基礎(chǔ)上,再探討幾個(gè)容易淡忘的概念,從源碼層面找原因,加深我們的理解,問題大概包括:

  • Spring的事務(wù)和數(shù)據(jù)庫的事務(wù)隔離是一個(gè)概念么?

  • Spring是如何實(shí)現(xiàn)事務(wù)的?

  • 事務(wù)隔離機(jī)制都有哪些?

  • 事務(wù)傳播機(jī)制都有哪些?

  • 查詢語句需要開事務(wù)么?

  • private方法加事務(wù)注解有用么?

  • 1、Spring的事務(wù)和數(shù)據(jù)庫的事務(wù)隔離是一個(gè)概念么?

    先來第一個(gè)問題,Spring的事務(wù)隔離級(jí)別和數(shù)據(jù)的事務(wù)隔離級(jí)別,是一回事么?

    其實(shí),數(shù)據(jù)庫一般只有4種隔離機(jī)制,Spring抽象出一種default,根據(jù)數(shù)據(jù)設(shè)置來變動(dòng)。

    • read uncommitted(未提交讀)

    • read committed(提交讀、不可重復(fù)讀)

    • repeatable read(可重復(fù)讀)

    • serializable(可串行化)

    • default (PlatformTransactionManager默認(rèn)的隔離級(jí)別,使用的就是數(shù)據(jù)庫默認(rèn)的)

    這是因?yàn)?#xff0c;Spring只提供統(tǒng)一事務(wù)管理接口,具體實(shí)現(xiàn)都是由各數(shù)據(jù)庫自己實(shí)現(xiàn)(如MySQL)。Spring會(huì)在事務(wù)開始時(shí),根據(jù)當(dāng)前環(huán)境中設(shè)置的隔離級(jí)別,調(diào)整數(shù)據(jù)庫隔離級(jí)別,由此保持一致。

    在DataSourceUtils文件中,代碼詳細(xì)的輸出了這個(gè)過程。

    // Apply specific isolation level, if any.
    Integer previousIsolationLevel = null;
    if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
    if (logger.isDebugEnabled()) {
    logger.debug("Changing isolation level of JDBC Connection [" + con + "] to " +
    definition.getIsolationLevel());
    }
    int currentIsolation = con.getTransactionIsolation();
    if (currentIsolation != definition.getIsolationLevel()) {
    previousIsolationLevel = currentIsolation;
    con.setTransactionIsolation(definition.getIsolationLevel());
    }
    }

    結(jié)論:三種情況,如果Spring沒有指定事務(wù)隔離級(jí)別,則會(huì)采用數(shù)據(jù)庫默認(rèn)的事務(wù)隔離級(jí)別;當(dāng)Spring指定了事務(wù)隔離級(jí)別,則會(huì)在代碼里將事務(wù)隔離級(jí)別修改為指定值;當(dāng)數(shù)據(jù)庫不支持這種隔離級(jí)別,效果則以數(shù)據(jù)庫的為準(zhǔn)(比如采用了MyISAM引擎)。

    我們會(huì)使用如下的方式進(jìn)行聲明。如果不是有性能和需求問題,就不要瞎改。事務(wù)處理弄不好是會(huì)鎖表的,而鎖表在大并發(fā)的情況下是會(huì)死人的。

    @Transactional(isolation = Isolation.READ_UNCOMMITTED)

    2、Spring事務(wù)的7種傳播機(jī)制

    只要寫代碼,代碼總會(huì)存在嵌套,或者循環(huán),造成了事務(wù)的嵌套或者循環(huán)。那么事務(wù)在這些情況下,根據(jù)配置會(huì)有不同的反應(yīng)。

    • REQUIRED 這是默認(rèn)的。表示當(dāng)前方法必須在一個(gè)具有事務(wù)的上下文中運(yùn)行,如有客戶端有事務(wù)在進(jìn)行,那么被調(diào)用端將在該事務(wù)中運(yùn)行,否則的話重新開啟一個(gè)事務(wù)。(如果被調(diào)用端發(fā)生異常,那么調(diào)用端和被調(diào)用端事務(wù)都將回滾)

    • REQUIRE_NEW 表示當(dāng)前方法必須運(yùn)行在它自己的事務(wù)中。如果存在當(dāng)前事務(wù),在該方法執(zhí)行期間,當(dāng)前事務(wù)會(huì)被掛起

    • NESTED ?如果當(dāng)前方法正有一個(gè)事務(wù)在運(yùn)行中,則該方法應(yīng)該運(yùn)行在一個(gè)嵌套事務(wù)中,被嵌套的事務(wù)可以獨(dú)立于被封裝的事務(wù)中進(jìn)行提交或者回滾。如果封裝事務(wù)存在,并且外層事務(wù)拋出異常回滾,那么內(nèi)層事務(wù)必須回滾,反之,內(nèi)層事務(wù)并不影響外層事務(wù)。如果封裝事務(wù)不存在,則同required的一樣

    • SUPPORTS 表示當(dāng)前方法不必需要具有一個(gè)事務(wù)上下文,但是如果有一個(gè)事務(wù)的話,它也可以在這個(gè)事務(wù)中運(yùn)行

    • NOT_SUPPORTED 表示該方法不應(yīng)該在一個(gè)事務(wù)中運(yùn)行。如果有一個(gè)事務(wù)正在運(yùn)行,他將在運(yùn)行期被掛起,直到這個(gè)事務(wù)提交或者回滾才恢復(fù)執(zhí)行

    • MANDATORY 表示當(dāng)前方法必須在一個(gè)事務(wù)中運(yùn)行,如果沒有事務(wù),將拋出異常

    • NEVER 表示當(dāng)方法務(wù)不應(yīng)該在一個(gè)事務(wù)中運(yùn)行,如果存在一個(gè)事務(wù),則拋出異常

    一般用得比較多的是REQUIRED , REQUIRES_NEW,用到其他的,你就要小心了,搞懂再用。

    最怕如果這倆字了,它會(huì)將事情搞的很復(fù)雜,尤其是代碼量大的時(shí)候,你永遠(yuǎn)不知道你寫的service會(huì)被誰用到。這就很尷尬了。

    我們會(huì)采用下面的方式進(jìn)行聲明。鑒于Spring的事務(wù)傳播非常的繞,如果功能滿足需求,那么就用默認(rèn)的就好,否則會(huì)引起不必要的麻煩。

    @Transactional(propagation=Propagation.REQUIRED)

    3、事務(wù)傳播機(jī)制是怎么實(shí)現(xiàn)的?

    事務(wù)傳播機(jī)制看似神奇,實(shí)際上是使用簡單的ThreadLocal的機(jī)制實(shí)現(xiàn)的。所以,如果調(diào)用的方法是在新線程調(diào)用的,事務(wù)傳播實(shí)際上是會(huì)失效的。這不同于我們以前講到的透傳,Spring并沒有做這樣的處理。

    參考:你的也是我的。3例ko多線程,局部變量透傳

    所以事務(wù)傳播機(jī)制,只有翻一遍源代碼,才能印象深刻。僅靠文字去傳播,很多東西會(huì)變得不可描述。


    如圖,PlatformTransactionManager只有簡單的三個(gè)抽象接口,定義了包含JDBC在內(nèi)的Spring所有的事務(wù)操作。

    我們平常說的JDBC,只是占到其中一部分。

    實(shí)現(xiàn)的方式,依然是使用AOP來實(shí)現(xiàn)的,具體的實(shí)現(xiàn)類是由TransactionAspectSupport來實(shí)現(xiàn)的。可以看到,代碼定義了一個(gè)叫做transactionInfoHolder的ThreadLocal變量,當(dāng)用到它的時(shí)候,就能夠確保在同一個(gè)線程下,獲取的變量是一致的。

    /**
    * Holder to support the {@code currentTransactionStatus()} method,
    * and to support communication between different cooperating advices
    * (e.g. before and after advice) if the aspect involves more than a
    * single method (as will be the case for around advice).
    */
    private static final ThreadLocal transactionInfoHolder =new NamedThreadLocal<>("Current aspect-driven transaction");

    具體的業(yè)務(wù)邏輯,是在invokeWithinTransaction中實(shí)現(xiàn)的。如果你繼續(xù)向下跟蹤的話,會(huì)找到AbstractPlatformTransactionManager類中的getTransaction方法。

    @Override
    public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)throws TransactionException {


    // Use defaults if no transaction definition given.
    TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());


    Object transaction = doGetTransaction();
    boolean debugEnabled = logger.isDebugEnabled();


    if (isExistingTransaction(transaction)) {
    // Existing transaction found -> check propagation behavior to find out how to behave.
    return handleExistingTransaction(def, transaction, debugEnabled);
    }


    // Check definition settings for new transaction.
    if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
    throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
    }


    // No existing transaction found -> check propagation behavior to find out how to proceed.
    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) {
    SuspendedResourcesHolder suspendedResources = suspend(null);
    if (debugEnabled) {
    logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
    }
    try {
    return startTransaction(def, transaction, debugEnabled, suspendedResources);
    }
    catch (RuntimeException | Error ex) {
    resume(null, suspendedResources);
    throw ex;
    }
    }
    else {
    // Create "empty" transaction: no actual transaction, but potentially synchronization.
    if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
    logger.warn("Custom isolation level specified but no actual transaction initiated; " +
    "isolation level will effectively be ignored: " + def);
    }
    boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
    return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
    }
    }

    不用我做過多解釋了吧,一切明顯的邏輯,都在代碼里。事務(wù)就是在這里創(chuàng)建的。

    4、查詢方法可以不開啟事務(wù)么?

    事務(wù)有個(gè)readonly,控制了事務(wù)的只讀屬性,和事務(wù)是否開啟沒半毛錢關(guān)系。

    在以前的一篇文章中,談到通過設(shè)置readonly屬性來控制語句的路由:”MySQL官方驅(qū)動(dòng)“主從分離的神秘面紗(掃盲篇),這其中就用到了事務(wù)的其中一個(gè)屬性readonly,它最終是體現(xiàn)在數(shù)據(jù)庫連接層面的。

    connection.setReadOnly(true);

    在Spring中的使用方式如下:

    @Transactional(readOnly=true)

    值得注意的是,這個(gè)屬性設(shè)置之后,并不是每個(gè)底層的數(shù)據(jù)庫都支持。中間層的ORM或者驅(qū)動(dòng),也可能會(huì)拿這個(gè)屬性做一些文章,所以與其說這個(gè)readonly是功能性的,不如說是一種暗示。

    拿MySQL來說,有兩種提交模式:

    • SET AUTOCOMMIT=0 禁止自動(dòng)提交

    • SET AUTOCOMMIT=1 開啟自動(dòng)提交

    這都是實(shí)打?qū)嵉腟QL語句,所以如果開啟了事務(wù),AUTOCOMMIT要為false。我們可以看到Spring做了以下幾個(gè)操作。

    con.setAutoCommit(false);

    如果是只讀事務(wù),還不忘手動(dòng)設(shè)置一下。

    if (isEnforceReadOnly() && definition.isReadOnly()) { try (Statement stmt = con.createStatement()) {
    stmt.executeUpdate("SET TRANSACTION READ ONLY");
    }
    }

    這種操作是很昂貴的,如果不加Transaction注解,默認(rèn)是不開啟事務(wù)的。單條的查詢語句也是沒有必要開啟事務(wù)的,數(shù)據(jù)庫默認(rèn)的配置就能滿足需求。

    但如果你一次執(zhí)行多條查詢語句,例如統(tǒng)計(jì)查詢,報(bào)表查詢,在這種場景下,多條查詢SQL必須保證整體的讀一致性,否則,在前條SQL查詢之后,后條SQL查詢之前,數(shù)據(jù)被其他用戶改變,就會(huì)造成數(shù)據(jù)的前后不一。

    也僅有在這種情況下,要開啟讀事務(wù)。

    5、private方法加事務(wù)注解有用么?

    @Transaction注解加在private上,并沒有什么卵用。

    這倒不是事務(wù)處理的代碼去寫的特性。由于事務(wù)的這些功能,是通過AOP方式強(qiáng)加進(jìn)去的,所以它收到動(dòng)態(tài)代理的控制。

    private和final修飾的方法,不會(huì)被代理。

    但是,你卻可以把private方法放在帶有事務(wù)功能的public方法里。這樣,它看起來也有了事務(wù)的一些功能特性,但它并沒有。

    End

    互聯(lián)網(wǎng)中,用到的事務(wù)并不多,很多都是非常小、速度非常快的接口,對(duì)于開發(fā)人員來說,事務(wù)是個(gè)累贅。

    但在一些帶有金融屬性的業(yè)務(wù)中,或者一些企業(yè)級(jí)開發(fā)應(yīng)用中,事務(wù)確實(shí)一個(gè)繞不過的坎。一旦深入其中,就會(huì)發(fā)現(xiàn)這個(gè)知識(shí)點(diǎn),露著血盆大口,等君入甕。

    xjjdog從源碼層次,聊到了幾個(gè)面試常問的問題。不要覺得奇怪,有的人確實(shí)一直在拿著臟讀、幻讀這樣的名詞來面試。

    而這些東西,都屬于當(dāng)時(shí)看了恍然大悟,第二天就繼續(xù)懵逼的內(nèi)容。

    什么時(shí)候,才能務(wù)實(shí)一點(diǎn)呢?

    近期熱門文章

    《996的樂趣,你是無法想象的》魔幻現(xiàn)實(shí)主義,關(guān)愛神經(jīng)衰弱

    《一切荒誕的傲慢,皆來源于認(rèn)知》不要被標(biāo)題給騙了,畫面感十足的消遣文章

    《必看!java后端,亮劍誅仙》后端技術(shù)索引,中肯火爆。全網(wǎng)轉(zhuǎn)載上百次。

    《學(xué)完這100多技術(shù),能當(dāng)架構(gòu)師么?(非廣告)》精準(zhǔn)點(diǎn)評(píng)100多框架,幫你選型

    作者簡介:小姐姐味道??(xjjdog),一個(gè)不允許程序員走彎路的公眾號(hào)。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。我的個(gè)人微信xjjdog0,歡迎添加好友,進(jìn)一步交流

    總結(jié)

    以上是生活随笔為你收集整理的spring更新后 外层事务查不到_再深一点:面试工作两不误,源码级理解Spring事务...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国内精品福利视频 | 国产剧情av引诱维修工 | 男人草女人 | 午夜视频一区二区 | 国产五区 | 人妻熟女一区二区三区app下载 | 日韩精品在线观看免费 | 女王人厕视频2ⅴk | 91大神久久 | aaa特级毛片 | 亚洲制服丝袜av | 国产99在线播放 | 亚洲精品电影在线 | 国产成人91| 国产 日韩 欧美 制服丝袜 | www..com国产 | 免费在线黄色网址 | 日本成人福利视频 | 长河落日电视连续剧免费观看 | 日韩视频一区二区三区在线播放免费观看 | 91理论片午午伦夜理片久久 | 日韩影视一区 | 亚洲男女视频 | 国产69精品久久久久久 | 日日夜夜干 | 欧美色乱 | 国产人妖一区 | 久草国产在线 | 欧美性猛交ⅹxx乱大交 | 国产三级在线观看完整版 | 免费吸乳羞羞网站视频 | 久久精品国产欧美亚洲人人爽 | 久久久久久91亚洲精品中文字幕 | 日本国产一区二区 | av免费看在线 | 欧美人妻少妇一区二区三区 | 久久99热这里只频精品6学生 | 日日夜操| 美女扒开屁股让男人捅 | 日韩精品一区二区三区四区五区 | 日本激情网站 | 国产成人a亚洲精v品无码 | 久热精品在线 | 亚洲成人黄色在线 | 黄色www视频 | 国产经典三级 | 国产1区 | 日本熟妇乱子伦xxxx | 亚洲欧美精品午睡沙发 | 经典三级久久 | 夜夜精品一区二区无码 | 日本一区二区不卡在线 | 国产av国片偷人妻麻豆 | 国产日韩欧美视频在线观看 | 午夜影院一区二区 | 欧美日韩国语 | 欧美日韩另类一区 | 九九热在线精品视频 | 国产乱人乱精一区二视频国产精品 | 不卡av片| 国产一级视频在线 | 激情小说图片视频 | 超碰在线公开 | 久草手机在线视频 | 懂色av一区二区三区蜜臀 | 三级自拍 | 亚洲国产成人精品视频 | 99精品国产免费 | 中文字幕无产乱码 | 欧美第二区| 无码精品一区二区免费 | 欧美性猛交bbbbb精品 | 日本美女全裸 | www.色就是色.com | 噼里啪啦国语版在线观看 | 极品国产一区 | 无码人妻黑人中文字幕 | 午夜综合 | 91福利区 | 欧美日韩操| 天堂中文8 | 桃花色综合影院 | 久久免费播放 | 国产精品一区二区在线 | 日韩欧美综合视频 | 久久国语精品 | 亚洲影音先锋 | 97成人资源 | 亚洲 日本 欧美 中文幕 | 国产精品--色哟哟 | 老外毛片 | 国产资源在线看 | 91麻豆产精品久久久久久 | 午夜亚洲国产 | 日本老少交| 超碰在线9 | 免费美女av | a级黄色小视频 | 17c国产精品一区二区 |