Spring事務(wù)

一、@Transactional

在使用Spring框架時(shí)璧函,可以有兩種使用事務(wù)的方式,一種是編程式的基显,一種是申明式的蘸吓,@Transactional注解就是申明式的。首先撩幽,事務(wù)這個(gè)概念是數(shù)據(jù)庫(kù)層面的库继,Spring只是基于數(shù)據(jù)庫(kù)中的事務(wù)進(jìn)行了擴(kuò)展,比如我們可以通過在某個(gè)方法上增加@Transactional注解窜醉,就可以開啟事務(wù)宪萄,這個(gè)方法中所有的sql都會(huì)在一個(gè)事務(wù)中執(zhí)行,統(tǒng)一成功或失敗榨惰。在一個(gè)方法上加了@Transactional注解后拜英,Spring會(huì)基于這個(gè)類生成一個(gè)代理對(duì)象,會(huì)將這個(gè)代理對(duì)象作為bean琅催,當(dāng)在使用這個(gè)代理對(duì)象的方法時(shí)居凶,如果這個(gè)方法上存在@Transactional注解,那么代理邏輯會(huì)先把事務(wù)的自動(dòng)提交設(shè)置為false恢暖,然后再去執(zhí)行原本的業(yè)務(wù)邏輯方法排监,如果執(zhí)行業(yè)務(wù)邏輯方法沒有
出現(xiàn)異常,那么代理邏輯中就會(huì)將事務(wù)進(jìn)行提交杰捂,如果執(zhí)行業(yè)務(wù)邏輯方法出現(xiàn)了異常舆床,那么則會(huì)將事務(wù)進(jìn)行回滾。當(dāng)然嫁佳,針對(duì)哪些異嘲ざ樱回滾事務(wù)是可以配置的,可以利用@Transactional注解中的rollbackFor屬性進(jìn)行配置蒿往,默認(rèn)情況下會(huì)對(duì)RuntimeException和Error進(jìn)行回滾盛垦。

二、事務(wù)的隔離級(jí)別

一個(gè)事務(wù)與其他事務(wù)的隔離的程度成為隔離級(jí)別瓤漏,以下是四種隔離級(jí)別腾夯,依次是變高的颊埃,隔離級(jí)別越高,數(shù)據(jù)的一致性就越好蝶俱,但也不是越高就越好班利,因?yàn)樵礁邔?duì)于性能的花銷就越大。開發(fā)中常用的隔離級(jí)別是讀已提交榨呆。以下是一些并發(fā)事務(wù)常見問題:

事務(wù)的四大特性分別是:原子性罗标、一致性、隔離性积蜻、持久性

幻讀和不可重復(fù)讀都是在同一個(gè)事務(wù)中多次讀取了其他事務(wù)已經(jīng)提交的事務(wù)的數(shù)據(jù)導(dǎo)致每次讀取的數(shù)據(jù)不一致闯割,所不同的是不可重復(fù)讀讀取的是同一條數(shù)據(jù),而幻讀針對(duì)的是一批數(shù)據(jù)整體的統(tǒng)計(jì)(比如數(shù)據(jù)的個(gè)數(shù))

1.讀未提交:READ UNCOMMITTED(可以讀到未提交的竿拆,可能會(huì)發(fā)生臟讀)
2.讀已提交:READ CONNITTED(可以避免臟讀)
3.可重復(fù)讀:REPEATABLE READ(可以避免不可重復(fù)讀)
4.串行化:SERIALIZABLE(可以避免幻讀)

以MYSQL數(shù)據(jù)庫(kù)來(lái)分析四種隔離級(jí)別

第一種隔離級(jí)別:Read uncommitted(讀未提交)
如果一個(gè)事務(wù)已經(jīng)開始寫數(shù)據(jù)宙拉,則另外一個(gè)事務(wù)不允許同時(shí)進(jìn)行寫操作,但允許其他事務(wù)讀此行數(shù)據(jù)如输,該隔離級(jí)別可以通過“排他寫鎖”鼓黔,但是不排斥讀線程實(shí)現(xiàn)央勒。這樣就避免了更新丟失不见,卻可能出現(xiàn)臟讀,也就是說事務(wù)B讀取到了事務(wù)A未提交的數(shù)據(jù)

同一個(gè)數(shù)據(jù)崔步,一個(gè)事務(wù)寫稳吮,另一個(gè)事務(wù)可以讀。

解決了更新丟失井濒,但還是可能會(huì)出現(xiàn)臟讀

第二種隔離級(jí)別:Read committed(讀提交)
如果是一個(gè)讀事務(wù)(線程)灶似,則允許其他事務(wù)讀寫,如果是寫事務(wù)將會(huì)禁止其他事務(wù)訪問該行數(shù)據(jù)瑞你,該隔離級(jí)別避免了臟讀酪惭,但是可能出現(xiàn)不可重復(fù)讀。事務(wù)A事先讀取了數(shù)據(jù)者甲,事務(wù)B緊接著更新了數(shù)據(jù)春感,并提交了事務(wù),而事務(wù)A再次讀取該數(shù)據(jù)時(shí)虏缸,數(shù)據(jù)已經(jīng)發(fā)生了改變鲫懒。

同一個(gè)數(shù)據(jù),一個(gè)事務(wù)寫刽辙,另一個(gè)事務(wù)不可以讀窥岩。一個(gè)事務(wù)讀,另一個(gè)事務(wù)可以讀寫宰缤。

解決了更新丟失和臟讀問題

第三種隔離級(jí)別:Repeatable read(可重復(fù)讀取)
可重復(fù)讀取是指在一個(gè)事務(wù)內(nèi)颂翼,多次讀同一個(gè)數(shù)據(jù)晃洒,在這個(gè)事務(wù)還沒結(jié)束時(shí),其他事務(wù)不能訪問該數(shù)據(jù)(包括了讀寫)朦乏,這樣就可以在同一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是一樣的锥累,因此稱為是可重復(fù)讀隔離級(jí)別,讀取數(shù)據(jù)的事務(wù)將會(huì)禁止寫事務(wù)(但允許讀事務(wù))集歇,寫事務(wù)則禁止任何其他事務(wù)(包括了讀寫)桶略,這樣避免了不可重復(fù)讀和臟讀,但是有時(shí)可能會(huì)出現(xiàn)幻讀诲宇。(讀取數(shù)據(jù)的事務(wù))可以通過“共享讀鎖”和“排他寫鎖”實(shí)現(xiàn)际歼。

幻讀產(chǎn)生
//行級(jí)排他鎖
select * from test for update
//行級(jí)共享鎖,注意可能會(huì)發(fā)生死鎖
select * from test lock in share mode
行級(jí)共享鎖

同一個(gè)數(shù)據(jù),一個(gè)事務(wù)讀姑蓝,另一個(gè)事務(wù)可以讀鹅心,一個(gè)事務(wù)寫,另一個(gè)事務(wù)既不可以讀也不可以寫纺荧。

解決了更新丟失旭愧、臟讀、不可重復(fù)讀宙暇、但是還會(huì)出現(xiàn)幻讀

第四種隔離級(jí)別:Serializable(可序化)
提供嚴(yán)格的事務(wù)隔離输枯,它要求事務(wù)序列化執(zhí)行,事務(wù)只能一個(gè)接著一個(gè)地執(zhí)行占贫,但不能并發(fā)執(zhí)行桃熄,如果僅僅通過“行級(jí)鎖”是無(wú)法實(shí)現(xiàn)序列化的,必須通過其他機(jī)制保證新插入的數(shù)據(jù)不會(huì)被執(zhí)行查詢操作的事務(wù)訪問到型奥。序列化是最高的事務(wù)隔離級(jí)別瞳收,同時(shí)代價(jià)也是最高的,性能很低厢汹,一般很少使用螟深,在該級(jí)別下,事務(wù)順序執(zhí)行烫葬,不僅可以避免臟讀界弧、不可重復(fù)讀,還避免了幻讀

解決了更新丟失厘灼、臟讀夹纫、不可重復(fù)讀、幻讀(虛讀)

臟讀
不可重復(fù)讀
幻讀
幻讀
事務(wù)隔離級(jí)別
事務(wù)隔離級(jí)別

如果數(shù)據(jù)庫(kù)的配置隔離級(jí)別是Read Commited设凹,而Spring配置的隔離級(jí)別是Repeatable Read舰讹,這時(shí)候以Spring配置的為準(zhǔn),如果Spring設(shè)置的隔離級(jí)別數(shù)據(jù)庫(kù)不支持闪朱,則效果取決于數(shù)據(jù)庫(kù)月匣。

mysql默認(rèn)的事務(wù)處理級(jí)別是'REPEATABLE-READ',也就是可重復(fù)讀
Oracle默認(rèn)系統(tǒng)事務(wù)隔離級(jí)別是READ COMMITTED,也就是讀已提交
SQL Server默認(rèn)系統(tǒng)事務(wù)隔離級(jí)別是READ COMMITTED,也就是讀已提交钻洒。

三、spring事務(wù)傳播機(jī)制

spring事務(wù)傳播機(jī)制是指锄开,多個(gè)事務(wù)方法相互調(diào)用時(shí)素标,事務(wù)如何在這些方法間傳播。方法A是一個(gè)事務(wù)的方法萍悴,方法A執(zhí)行過程中調(diào)用了方法B头遭,那么方法B有無(wú)事務(wù)以及方法B對(duì)事務(wù)的要求不同都會(huì)對(duì)方法A的事務(wù)具體執(zhí)行造成影響,同時(shí)方法A的事務(wù)對(duì)方法B的事務(wù)執(zhí)行也有影響癣诱,這種影響具體是什么由兩個(gè)方法所定義的事務(wù)傳播類型決定计维。

七種傳播機(jī)制

NESTED的重點(diǎn)是作為調(diào)用方的一個(gè)嵌套。

NESTED和REQUIRES_NEW的區(qū)別:REQUIRES_NEW是新建一個(gè)事務(wù)并且新開啟的這個(gè)事務(wù)與原有事務(wù)無(wú)關(guān)撕予,而NESTED則是當(dāng)前存在事務(wù)時(shí)(我們把當(dāng)前事務(wù)稱之為父事務(wù))會(huì)開啟一個(gè)嵌套事務(wù)(稱之為一個(gè)子事務(wù))鲫惶。 在NESTED情況下父事務(wù)回滾時(shí),子事務(wù)也會(huì)回滾实抡,而在REQUIRES_NEW情況下欠母,原有事務(wù)回滾,不會(huì)影響新開啟的事務(wù)吆寨。

NESTED和REQUIRED的區(qū)別:REQUIRED情況下赏淌,調(diào)用方存在事務(wù)時(shí),則被調(diào)用方和調(diào)用方使用同一事務(wù)鸟废,那么被調(diào)用方出現(xiàn)異常時(shí)猜敢,由于共用一個(gè)事務(wù),所以無(wú)論調(diào)用方是否catch其異常盒延,事務(wù)都會(huì)回滾,而在NESTED情況下鼠冕,被調(diào)用方發(fā)生異常時(shí)添寺,調(diào)用方可以catch其異常,這樣只有子事務(wù)回滾懈费,父事務(wù)不受影響计露。

事務(wù)的傳播屬性通過@Transactional注解中對(duì)屬性propagation=" "來(lái)進(jìn)行配置,默認(rèn)是“REQUIRED”是運(yùn)行原來(lái)的事務(wù)憎乙,還有一個(gè)常用的是"REQUIRED_NEW"開啟新的事務(wù)票罐,舉例來(lái)說,購(gòu)買東西是一個(gè)事務(wù)泞边,購(gòu)買每一本書又是一個(gè)事務(wù)该押,在購(gòu)買事務(wù)中調(diào)用購(gòu)買書,假如余額只有100塊阵谚,買兩本書蚕礼,一本是50烟具,一本是60。這樣的話默認(rèn)的就是在原來(lái)的事務(wù)奠蹬,錢不足是不會(huì)執(zhí)行成功朝聋,REQUIRED_NEW就會(huì)開啟新事務(wù),則會(huì)買一本書囤躁。

四冀痕、spring事務(wù)什么時(shí)候會(huì)失效

spring事務(wù)的原理是AOP,進(jìn)行了切面增強(qiáng)狸演,那么失效的根本原因是AOP不起作用了金度!
常見情況有如下幾種:
1、發(fā)生自調(diào)用严沥,類里面使用this調(diào)用本類的方法(this通常省略)猜极,此時(shí)這個(gè)this對(duì)象不是代理類,而是UserService對(duì)象本身消玄!解決方法很簡(jiǎn)單跟伏,讓那個(gè)this變成UserService的代理類即可!
2翩瓜、方法不是public的
@Transactional 只能用于 public 的方法上受扳,否則事務(wù)不會(huì)失效,如果要用在非 public 方法上兔跌,可 以開啟 AspectJ 代理模式勘高。
3、數(shù)據(jù)庫(kù)不支持事務(wù)
4坟桅、沒有被spring管理
5华望、異常被吃掉,事務(wù)不會(huì)回滾(或者拋出的異常沒有被定義仅乓,默認(rèn)為RuntimeException)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赖舟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子夸楣,更是在濱河造成了極大的恐慌宾抓,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豫喧,死亡現(xiàn)場(chǎng)離奇詭異石洗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)紧显,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門讲衫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鸟妙,你說我怎么就攤上這事焦人』映常” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵花椭,是天一觀的道長(zhǎng)忽匈。 經(jīng)常有香客問我,道長(zhǎng)矿辽,這世上最難降的妖魔是什么丹允? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮袋倔,結(jié)果婚禮上雕蔽,老公的妹妹穿的比我還像新娘。我一直安慰自己宾娜,他們只是感情好批狐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著前塔,像睡著了一般嚣艇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上华弓,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天食零,我揣著相機(jī)與錄音,去河邊找鬼寂屏。 笑死贰谣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的迁霎。 我是一名探鬼主播吱抚,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼欧引!你這毒婦竟也來(lái)了频伤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤芝此,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后因痛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體婚苹,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年鸵膏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了膊升。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谭企,死狀恐怖廓译,靈堂內(nèi)的尸體忽然破棺而出评肆,到底是詐尸還是另有隱情,我是刑警寧澤非区,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布瓜挽,位于F島的核電站,受9級(jí)特大地震影響征绸,放射性物質(zhì)發(fā)生泄漏久橙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一管怠、第九天 我趴在偏房一處隱蔽的房頂上張望淆衷。 院中可真熱鬧,春花似錦渤弛、人聲如沸祝拯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)佳头。三九已至,卻和暖如春辕宏,著一層夾襖步出監(jiān)牢的瞬間畜晰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工瑞筐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凄鼻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓聚假,卻偏偏與公主長(zhǎng)得像块蚌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子膘格,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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