<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring官方都推薦使用的@Transactional事務(wù),為啥我不建議使用!

          共 3235字,需瀏覽 7分鐘

           ·

          2020-10-22 01:24

          △Hollis, 一個(gè)對(duì)Coding有著獨(dú)特追求的人△
          這是Hollis的第?309?篇原創(chuàng)分享
          作者 l Hollis
          來源 l Hollis(ID:hollischuang)
          事務(wù)管理在系統(tǒng)開發(fā)中是不可缺少的一部分,Spring提供了很好事務(wù)管理機(jī)制,主要分為編程式事務(wù)和聲明式事務(wù)兩種。
          關(guān)于事務(wù)的基礎(chǔ)知識(shí),如什么是事務(wù),數(shù)據(jù)庫(kù)事務(wù)以及Spring事務(wù)的ACID、隔離級(jí)別、傳播機(jī)制、行為等,就不在這篇文章中詳細(xì)介紹了。默認(rèn)大家都有一定的了解。
          本文,作者會(huì)先簡(jiǎn)單介紹下什么是聲明式事務(wù)和編程式事務(wù),再說一下為什么我不建議使用聲明式事務(wù)。



          編程式事務(wù)
          基于底層的API,如PlatformTransactionManager、TransactionDefinition 和 TransactionTemplate 等核心接口,開發(fā)者完全可以通過編程的方式來進(jìn)行事務(wù)管理。
          編程式事務(wù)方式需要是開發(fā)者在代碼中手動(dòng)的管理事務(wù)的開啟、提交、回滾等操作。

          public?void?test()?{

          ??????TransactionDefinition?def?=?new?DefaultTransactionDefinition();

          ??????TransactionStatus?status?=?transactionManager.getTransaction(def);



          ???????try?{

          ?????????//?事務(wù)操作

          ?????????//?事務(wù)提交

          ?????????transactionManager.commit(status);

          ??????}?catch?(DataAccessException?e)?{

          ?????????//?事務(wù)提交

          ?????????transactionManager.rollback(status);

          ?????????throw?e;

          ??????}

          }

          如以上代碼,開發(fā)者可以通過API自己控制事務(wù)。



          聲明式事務(wù)
          聲明式事務(wù)管理方法允許開發(fā)者配置的幫助下來管理事務(wù),而不需要依賴底層API進(jìn)行硬編碼。開發(fā)者可以只使用注解或基于配置的 XML 來管理事務(wù)。

          @Transactional

          public?void?test()?{

          ?????//?事務(wù)操作??

          }

          如上,使用@Transactional即可給test方法增加事務(wù)控制。
          當(dāng)然,上面的代碼只是簡(jiǎn)化后的,想要使用事務(wù)還需要一些配置內(nèi)容。這里就不詳細(xì)闡述了。
          這兩種事務(wù),格子有各自的優(yōu)缺點(diǎn),那么,各自有哪些適合的場(chǎng)景呢?為什么有人會(huì)拒絕使用聲明式事務(wù)呢?



          聲明式事務(wù)的優(yōu)點(diǎn)
          通過上面的例子,其實(shí)我們可以很容易的看出來,聲明式事務(wù)幫助我們節(jié)省了很多代碼,他會(huì)自動(dòng)幫我們進(jìn)行事務(wù)的開啟、提交以及回滾等操作,把程序員從事務(wù)管理中解放出來。
          聲明式事務(wù)管理使用了 AOP 實(shí)現(xiàn)的,本質(zhì)就是在目標(biāo)方法執(zhí)行前后進(jìn)行攔截。 在目標(biāo)方法執(zhí)行前加入或創(chuàng)建一個(gè)事務(wù),在執(zhí)行方法執(zhí)行后,根據(jù)實(shí)際情況選擇提交或是回滾事務(wù)。
          使用這種方式,對(duì)代碼沒有侵入性,方法內(nèi)只需要寫業(yè)務(wù)邏輯就可以了。
          但是,聲明式事務(wù)真的有這么好么?倒也不見得。



          聲明式事務(wù)的粒度問題
          首先,聲明式事務(wù)有一個(gè)局限,那就是他的最小粒度要作用在方法上。
          也就是說,如果想要給一部分代碼塊增加事務(wù)的話,那就需要把這個(gè)部分代碼塊單獨(dú)獨(dú)立出來作為一個(gè)方法。
          但是,正是因?yàn)檫@個(gè)粒度問題,本人并不建議過度的使用聲明式事務(wù)。
          首先,因?yàn)槁暶魇绞聞?wù)是通過注解的,有些時(shí)候還可以通過配置實(shí)現(xiàn),這就會(huì)導(dǎo)致一個(gè)問題,那就是這個(gè)事務(wù)有可能被開發(fā)者忽略。
          事務(wù)被忽略了有什么問題呢?
          首先,如果開發(fā)者沒有注意到一個(gè)方法是被事務(wù)嵌套的,那么就可能會(huì)再方法中加入一些如RPC遠(yuǎn)程調(diào)用、消息發(fā)送、緩存更新、文件寫入等操作。
          我們知道,這些操作如果被包在事務(wù)中,有兩個(gè)問題:
          1、這些操作自身是無法回滾的,這就會(huì)導(dǎo)致數(shù)據(jù)的不一致。可能RPC調(diào)用成功了,但是本地事務(wù)回滾了,可是PRC調(diào)用無法回滾了。
          2、在事務(wù)中有遠(yuǎn)程調(diào)用,就會(huì)拉長(zhǎng)整個(gè)事務(wù)。那么久會(huì)導(dǎo)致本事務(wù)的數(shù)據(jù)庫(kù)連接一直被占用,那么如果類似操作過多,就會(huì)導(dǎo)致數(shù)據(jù)庫(kù)連接池耗盡。
          有些時(shí)候,即使沒有在事務(wù)中進(jìn)行遠(yuǎn)程操作,但是有些人還是可能會(huì)不經(jīng)意的進(jìn)行一些內(nèi)存操作,如運(yùn)算。或者如果遇到分庫(kù)分表的情況,有可能不經(jīng)意間進(jìn)行跨庫(kù)操作。
          但是如果是編程式事務(wù)的話,業(yè)務(wù)代碼中就會(huì)清清楚楚看到什么地方開啟事務(wù),什么地方提交,什么時(shí)候回滾。這樣有人改這段代碼的時(shí)候,就會(huì)強(qiáng)制他考慮要加的代碼是否應(yīng)該方法事務(wù)內(nèi)。
          有些人可能會(huì)說,已經(jīng)有了聲明式事務(wù),但是寫代碼的人沒注意,這能怪誰。
          話雖然是這么說,但是我們還是希望可以通過一些機(jī)制或者規(guī)范,降低這些問題發(fā)生的概率。
          比如建議大家使用編程式事務(wù),而不是聲明式事務(wù)。因?yàn)?,作者工作這么多年來,發(fā)生過不止一次開發(fā)者沒注意到聲明式事務(wù)而導(dǎo)致的故障。
          因?yàn)橛行r(shí)候,聲明式事務(wù)確實(shí)不夠明顯。



          聲明式事務(wù)用不對(duì)容易失效
          除了事務(wù)的粒度問題,還有一個(gè)問題那就是聲明式事務(wù)雖然看上去幫我們簡(jiǎn)化了很多代碼,但是一旦沒用對(duì),也很容易導(dǎo)致事務(wù)失效。
          如以下幾種場(chǎng)景就可能導(dǎo)致聲明式事務(wù)失效:
          1、@Transactional 應(yīng)用在非 public 修飾的方法上
          2、@Transactional 注解屬性 propagation 設(shè)置錯(cuò)誤
          3、@Transactional 注解屬性 rollbackFor 設(shè)置錯(cuò)誤
          4、同一個(gè)類中方法調(diào)用,導(dǎo)致@Transactional失效
          5、異常被catch捕獲導(dǎo)致@Transactional失效
          6、數(shù)據(jù)庫(kù)引擎不支持事務(wù)
          以上幾個(gè)問題,如果使用編程式事務(wù)的話,很多都是可以避免的。
          使用聲明事務(wù)失效的問題我們發(fā)生過很多次。不知道大家有沒有遇到過,我是實(shí)際遇到過的
          因?yàn)镾pring的事務(wù)是基于AOP實(shí)現(xiàn)的,但是在代碼中,有時(shí)候我們會(huì)有很多切面,不同的切面可能會(huì)來處理不同的事情,多個(gè)切面之間可能會(huì)有相互影響。
          在之前的一個(gè)項(xiàng)目中,我就發(fā)現(xiàn)我們的Service層的事務(wù)全都失效了,一個(gè)SQL執(zhí)行失敗后并沒有回滾,排查下來才發(fā)現(xiàn),是因?yàn)橐晃煌滦略隽艘粋€(gè)切面,這個(gè)切面里面做個(gè)異常的統(tǒng)一捕獲,導(dǎo)致事務(wù)的切面沒有捕獲到異常,導(dǎo)致事務(wù)無法回滾。
          這樣的問題,發(fā)生過不止一次,而且不容易被發(fā)現(xiàn)。
          很多人還是會(huì)說,說到底還是自己能力不行,對(duì)事務(wù)理解不透徹,用錯(cuò)了能怪誰。
          但是我還是那句話,我們確實(shí)無法保證所有人的能力都很高,也無法要求所有開發(fā)者都能不出錯(cuò)。我們能做的就是,盡量可以通過機(jī)制或者規(guī)范,來避免或者降低這些問題發(fā)生的概率。
          其實(shí),如果大家有認(rèn)真看過阿里巴巴出的那份Java開發(fā)手冊(cè)的話,其實(shí)就能發(fā)現(xiàn),其中的很多規(guī)約并不是完完全全容易被人理解,有些也比較生硬,但是其實(shí),這些規(guī)范都是從無數(shù)個(gè)坑里爬出來的開發(fā)者們總結(jié)出來的。
          關(guān)于@Transactional的用法,規(guī)約中也有提到過,只不過規(guī)約中的觀點(diǎn)沒有我這么鮮明:



          總結(jié)
          最后,相信本文的觀點(diǎn)很多人都并不一定認(rèn)同,很多人會(huì)說:Spring官方都推薦無侵入性的聲明式事務(wù),你有啥資格出來BB 。
          說實(shí)話,剛工作的前幾年,我也熱衷于使用聲明式事務(wù),覺得很干凈,也很"優(yōu)雅"。覺得師兄們使用編程式事務(wù)多此一舉,沒有工匠精神。
          但是慢慢的,線上發(fā)生過幾次問題之后,我們復(fù)盤后發(fā)現(xiàn),很多時(shí)候你自己寫的代碼很優(yōu)雅,這完全沒問題。
          但是,優(yōu)雅的同時(shí)也帶來了一些副作用,師兄們又不能批評(píng)我,因?yàn)槲业挠梅ù_實(shí)沒錯(cuò)…
          所以,有些事,還是要痛過之后才知道。
          當(dāng)然,本文并不要求大家一定要徹底不使用聲明式事務(wù),只是建議大家日后在使用事務(wù)的時(shí)候,能夠考慮到本文中提到的觀點(diǎn),然后自行選擇。



          瀏覽 28
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久夜精品视频 | 亚洲高清资源 | 激情丁香月婷爱网 | 天天色,天天干,天天 | 国产传媒天美果冻精品亚洲一区二区三区直播 |