就這?一篇文章讓你讀懂 Spring 事務(wù)

什么是事務(wù)

img

▲ 百度百科

概括來(lái)講仅偎,事務(wù)是一個(gè)由有限操作集合組成的邏輯單元跨蟹。事務(wù)操作包含兩個(gè)目的,數(shù)據(jù)一致以及操作隔離橘沥。數(shù)據(jù)一致是指事務(wù)提交時(shí)保證事務(wù)內(nèi)的所有操作都成功完成窗轩,并且更改永久生效;事務(wù)回滾時(shí)座咆,保證能夠恢復(fù)到事務(wù)執(zhí)行之前的狀態(tài)痢艺。操作隔離則是指多個(gè)同時(shí)執(zhí)行的事務(wù)之間應(yīng)該相互獨(dú)立,互不影響介陶。

img

靚仔和小明的銀行賬戶都有1000元堤舒,靚仔要給小明轉(zhuǎn)賬500元。

這個(gè)過(guò)程看似簡(jiǎn)單哺呜,實(shí)際上涉及了一系列的數(shù)據(jù)庫(kù)操作舌缤,可以簡(jiǎn)單地視為兩步基本操作,即從靚仔帳戶的金額中扣除500元某残,以及將小明帳戶中金額添加500元国撵。

假設(shè)第一步數(shù)據(jù)庫(kù)操作成功,第二步失敗了玻墅,那就會(huì)出現(xiàn)小明賬戶金額沒(méi)變介牙,靚仔卻白白少了500元的情況,靚仔豈不是很悲催椭豫。

事務(wù)機(jī)制可以避免此類情況耻瑟,以保證整個(gè)操作的完成,如果某步操作出錯(cuò)赏酥,之前所做的數(shù)據(jù)庫(kù)操作將全部失效喳整。

事務(wù)的特性

提到事務(wù),不可避免需要涉及到事務(wù)的四個(gè)特性(ACID):

  • 原子性(Atomicity):事務(wù)作為一個(gè)整體被執(zhí)行裸扶,包含在其中的對(duì)數(shù)據(jù)庫(kù)的操作要么全部被執(zhí)行框都,要么都不執(zhí)行。

  • 一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫(kù)的狀態(tài)從一個(gè)一致?tīng)顟B(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致?tīng)顟B(tài)呵晨。一致?tīng)顟B(tài)的含義是數(shù)據(jù)庫(kù)中的數(shù)據(jù)應(yīng)滿足完整性約束魏保。

  • 隔離性(Isolation):多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行摸屠。

  • 持久性(Durability):已被提交的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改應(yīng)該永久保存在數(shù)據(jù)庫(kù)中谓罗。

我們將嚴(yán)格遵循 ACID 屬性的事務(wù)稱為剛性事務(wù)。與之相對(duì)季二,期望最終一致性檩咱,在事務(wù)執(zhí)行的中間狀態(tài)允許暫時(shí)不遵循 ACID 屬性的事務(wù)稱為柔性事務(wù)揭措,柔性事務(wù)的使用涉及到分布式事務(wù)方案,后續(xù)將為大家擴(kuò)展刻蚯,這里就不過(guò)多闡述绊含。

Spring 事務(wù)管理的方式

1、編程式事務(wù)管理

編程式事務(wù)管理是侵入性事務(wù)管理炊汹,可通過(guò) PlatformTransactionManager 實(shí)現(xiàn)來(lái)進(jìn)行事務(wù)管理躬充,Spring 提供了模板類 TransactionTemplate 進(jìn)行事務(wù)管理。

2讨便、聲明式事務(wù)管理

聲明式事務(wù)管理建立在 AOP 之上充甚,有兩種常用的方式,一是基于 tx 和 aop 命名空間的 xml 配置文件霸褒,一是基于 @Transactional 注解津坑,隨著 Spring 和 Java 的版本越來(lái)越高,越趨向于使用注解的方式傲霸。

其本質(zhì)是對(duì)方法前后進(jìn)行攔截,然后在目標(biāo)方法開(kāi)始之前創(chuàng)建或者加入一個(gè)事務(wù)眉反,執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行的情況提交或者回滾昙啄。

聲明式事務(wù)屬于無(wú)侵入式,不會(huì)影響業(yè)務(wù)邏輯的實(shí)現(xiàn)寸五,只需要在配置文件中做相關(guān)的事務(wù)規(guī)則聲明或者通過(guò)注解的方式梳凛,便可以將事務(wù)規(guī)則應(yīng)用到業(yè)務(wù)邏輯中。而編程式事務(wù)每次實(shí)現(xiàn)都要單獨(dú)實(shí)現(xiàn)梳杏,但業(yè)務(wù)量大功能復(fù)雜時(shí)韧拒,使用編程式事務(wù)無(wú)疑是痛苦的。

顯然聲明式事務(wù)管理比編程式事務(wù)管理更可取十性,盡管它不如編程式事務(wù)管理靈活叛溢,這正是 Spring 倡導(dǎo)的非侵入式的編程方式。

順便了解下注解 @Transactional 的作用范圍:

  1. 方法 :推薦將注解使用于方法上劲适,不過(guò)需要注意的是:該注解只能應(yīng)用到 public 方法上楷掉,否則不生效。

  2. 類 :如果這個(gè)注解使用在類上的話霞势,表明該注解對(duì)該類中所有的 public 方法都生效烹植。

  3. 接口 :不推薦在接口上使用。

Spring 事務(wù)管理的五大屬性

img

1愕贡、事務(wù)的隔離級(jí)別

當(dāng)有多個(gè)事務(wù)同時(shí)執(zhí)行時(shí)草雕,就可能出現(xiàn)下面這些問(wèn)題:

  • 臟讀:一個(gè)事務(wù)讀取了另一個(gè)事務(wù)未提交的數(shù)據(jù)。

  • 不可重復(fù)讀:一個(gè)事務(wù)先后讀取相同的數(shù)據(jù)固以,發(fā)現(xiàn)兩次讀取的數(shù)據(jù)內(nèi)容不一致墩虹。

  • 幻讀:一個(gè)事務(wù)按相同的查詢條件重新讀取以前檢索過(guò)的數(shù)據(jù),卻發(fā)現(xiàn)其它事務(wù)插入了滿足其查詢條件的新數(shù)據(jù)

而事務(wù)的隔離級(jí)別就定義了并發(fā)事務(wù)活動(dòng)影響的程度。

  • ISOLATION_DEFAULT:使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別(MySQL 默認(rèn)采用的REPEATABLE_READ 隔離級(jí)別 Oracle 默認(rèn)采用的 READ_COMMITTED 隔離級(jí)別)

  • ISOLATION_READ_UNCOMMITTED:允許讀取尚未提交的更改败晴,這是最低的隔離級(jí)別浓冒,很少會(huì)使用〖饫ぃ可能導(dǎo)致臟讀稳懒、幻讀或不可重復(fù)讀

  • ISOLATION_READ_COMMITTED:允許從已經(jīng)提交的并發(fā)事務(wù)讀取慢味。可防止臟讀场梆,但幻讀和不可重復(fù)讀仍可能會(huì)發(fā)生

  • ISOLATION_REPEATABLE_READ:對(duì)相同字段的多次讀取的結(jié)果是一致的纯路,除非數(shù)據(jù)被當(dāng)前事務(wù)本身改變或油。可防止臟讀和不可重復(fù)讀,但幻讀仍可能發(fā)生驰唬。

  • ISOLATION_SERIALIZABLE: 最高的隔離級(jí)別顶岸,完全服從 ACID 的隔離級(jí)別。所有的事務(wù)依次逐個(gè)執(zhí)行叫编,這樣事務(wù)之間就完全不可能產(chǎn)生干擾辖佣,也就是說(shuō),該級(jí)別可以防止臟讀搓逾、不可重復(fù)讀以及幻讀卷谈。但是這在所有隔離級(jí)別中也是性能最差的,因?yàn)樗ǔJ峭ㄟ^(guò)完全鎖定當(dāng)前事務(wù)所涉及的數(shù)據(jù)表來(lái)完成的霞篡。通常情況下也不會(huì)用到該級(jí)別世蔗。

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

事務(wù)的傳播機(jī)制是為了解決事務(wù)嵌套的場(chǎng)景下朗兵,如何處理事務(wù)的問(wèn)題污淋。

  • PROPAGATION_REQUIRED(默認(rèn)):

  • 如果該方法執(zhí)行在沒(méi)有事務(wù)的方法中,就創(chuàng)建一個(gè)新的事務(wù)余掖。

  • 如果執(zhí)行在已經(jīng)存在事務(wù)的方法中芙沥,則加入到這個(gè)事務(wù)中,合并成一個(gè)事務(wù)浊吏。

  • PROPAGATION_SUPPORTS:

  • 如果該方法執(zhí)行在沒(méi)有事務(wù)的方法中而昨,就以非事務(wù)方式執(zhí)行。

  • 如果執(zhí)行在已經(jīng)存在事務(wù)的方法中找田,則加入到這個(gè)事務(wù)中歌憨,合并成一個(gè)事務(wù)。

  • PROPAGATION_MANDATORY:

  • 如果該方法執(zhí)行在沒(méi)有事務(wù)的方法中墩衙,就拋出異常务嫡。

  • 如果執(zhí)行在已經(jīng)存在事務(wù)的方法中甲抖,則加入到這個(gè)事務(wù)中,合并成一個(gè)事務(wù)心铃。

  • PROPAGATION_REQUIRES_NEW:

  • 無(wú)論該方法是否執(zhí)行在事務(wù)的方法中准谚,都創(chuàng)建一個(gè)新的事務(wù)。

  • 不過(guò)如果執(zhí)行在存在事務(wù)的方法中去扣,就將方法中的事務(wù)暫時(shí)掛起柱衔。

  • 新的事務(wù)會(huì)獨(dú)立提交與回滾,不受調(diào)用它的父方法的事務(wù)影響愉棱。

  • PROPAGATION_NOT_SUPPORTED:

  • 無(wú)論該方法是否執(zhí)行在事務(wù)的方法中唆铐,都以非事務(wù)方式執(zhí)行。

  • 不過(guò)如果執(zhí)行在存在事務(wù)的方法中奔滑,就將該事務(wù)暫時(shí)掛起艾岂。

  • PROPAGATION_NEVER:

  • 如果該方法執(zhí)行在沒(méi)有事務(wù)的方法中,就也以非事務(wù)方式執(zhí)行朋其。

  • 不過(guò)如果執(zhí)行在存在事務(wù)的方法中王浴,就拋出異常。

  • PROPAGATION_NESTED:

  • 如果該方法執(zhí)行在沒(méi)有事務(wù)的方法中梅猿,就創(chuàng)建一個(gè)新的事務(wù)叼耙。

  • 如果執(zhí)行在已經(jīng)存在事務(wù)的方法中,則在當(dāng)前事務(wù)中嵌套創(chuàng)建子事務(wù)執(zhí)行粒没。

  • 被嵌套的事務(wù)可以獨(dú)立于封裝事務(wù)進(jìn)行提交或回滾。

  • 如果外部事務(wù)提交嵌套事務(wù)也會(huì)被提交簇爆,如果外部事務(wù)回滾嵌套事務(wù)也會(huì)進(jìn)行回滾癞松。

3、只讀

如果一個(gè)事務(wù)只包含了對(duì)數(shù)據(jù)庫(kù)查詢操作入蛆,那么可以利用事務(wù)的只讀特性响蓉,將事務(wù)類型指定為 readonly 。只讀事務(wù)下哨毁,數(shù)據(jù)庫(kù)會(huì)進(jìn)行一些優(yōu)化枫甲。

有同學(xué)可能會(huì)問(wèn)了,為什么查詢操作還要加事務(wù)扼褪?

例如在做統(tǒng)計(jì)查詢或者報(bào)表查詢這樣的場(chǎng)景下想幻,可能會(huì)涉及多個(gè)查詢,多條查詢 SQL 必須保證整體的讀一致性话浇,否則脏毯,在前一條 SQL 查詢之后,后一條 SQL 查詢之前幔崖,數(shù)據(jù)被其他用戶改變食店,那么這次整體的統(tǒng)計(jì)查詢將會(huì)出現(xiàn)讀數(shù)據(jù)不一致的狀態(tài)渣淤,此時(shí),就應(yīng)該啟用事務(wù)支持吉嫩。

4价认、事務(wù)超時(shí)

事務(wù)超時(shí)指的是一個(gè)事務(wù)所允許執(zhí)行的最長(zhǎng)時(shí)間,如果超過(guò)該時(shí)間限制但事務(wù)還沒(méi)有完成自娩,就會(huì)自動(dòng)回滾事務(wù)用踩,避免長(zhǎng)時(shí)間運(yùn)行的事務(wù)會(huì)不必要地占用數(shù)據(jù)庫(kù)資源。

5椒功、回滾規(guī)則

默認(rèn)情況下捶箱,事務(wù)只在出現(xiàn)運(yùn)行時(shí)異常(runtime exception)時(shí)回滾,Error 也會(huì)導(dǎo)致事務(wù)回滾动漾,但是在出現(xiàn)受檢查異常(checked exception)時(shí)不回滾丁屎。

不過(guò),可以聲明在出現(xiàn)特定受檢查異常時(shí)像運(yùn)行時(shí)異常一樣回滾旱眯。同樣晨川,也可以聲明一個(gè)事務(wù)在出現(xiàn)特定的異常時(shí)不回滾,即使特定的異常是運(yùn)行時(shí)異常删豺。

總結(jié)

以上就是靚仔對(duì) Spring 事務(wù)的理解共虑,如有不足,也歡迎朋友們指正呀页。

后面將會(huì)為大家介紹事務(wù)失效的幾大場(chǎng)景妈拌,以及解決方案,敬請(qǐng)期待蓬蝶!

往期推薦

最詳細(xì)的圖文解析Java各種鎖(終極篇)

SpringBoot+Redis 實(shí)現(xiàn)消息訂閱發(fā)布

什么尘分?你還不會(huì)在GitHub上搜索資源?還不點(diǎn)進(jìn)來(lái)看看丸氛?

一定要收藏的5個(gè)優(yōu)秀的SpringCloud開(kāi)源項(xiàng)目

一定要收藏的5個(gè)后臺(tái)管理系統(tǒng)的前端框架

更多文章可以關(guān)注同名公眾號(hào)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末培愁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缓窜,更是在濱河造成了極大的恐慌定续,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禾锤,死亡現(xiàn)場(chǎng)離奇詭異私股,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)恩掷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)庇茫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人螃成,你說(shuō)我怎么就攤上這事旦签〔槠海” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵宁炫,是天一觀的道長(zhǎng)偿曙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)羔巢,這世上最難降的妖魔是什么望忆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮竿秆,結(jié)果婚禮上启摄,老公的妹妹穿的比我還像新娘。我一直安慰自己幽钢,他們只是感情好歉备,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著匪燕,像睡著了一般蕾羊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帽驯,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天龟再,我揣著相機(jī)與錄音,去河邊找鬼尼变。 笑死利凑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嫌术。 我是一名探鬼主播哀澈,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蛉威!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起走哺,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蚯嫌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后丙躏,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體择示,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年晒旅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栅盲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡废恋,死狀恐怖谈秫,靈堂內(nèi)的尸體忽然破棺而出扒寄,到底是詐尸還是另有隱情,我是刑警寧澤拟烫,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布该编,位于F島的核電站,受9級(jí)特大地震影響硕淑,放射性物質(zhì)發(fā)生泄漏课竣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一置媳、第九天 我趴在偏房一處隱蔽的房頂上張望于樟。 院中可真熱鬧,春花似錦拇囊、人聲如沸迂曲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)奢米。三九已至,卻和暖如春纠永,著一層夾襖步出監(jiān)牢的瞬間鬓长,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工尝江, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涉波,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓炭序,卻偏偏與公主長(zhǎng)得像啤覆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惭聂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容