摘要:事務(wù)隔離級別定義了一個(gè)事務(wù)可能受其他并發(fā)事務(wù)影響的程度我們先來看一下并發(fā)事務(wù)帶來的問題,然后再來介紹一下接口中定義了五個(gè)表示隔離級別的常量。
Java面試通關(guān)手冊(Java學(xué)習(xí)指南):https://github.com/Snailclimb/Java_Guide
微信閱讀地址鏈接:可能是最漂亮的Spring事務(wù)管理詳解
事務(wù)概念回顧什么是事務(wù)?
事務(wù)是邏輯上的一組操作,要么都執(zhí)行,要么都不執(zhí)行.
事物的特性(ACID):
原子性: 事務(wù)是最小的執(zhí)行單位,不允許分割。事務(wù)的原子性確保動(dòng)作要么全部完成,要么完全不起作用;
一致性: 執(zhí)行事務(wù)前后,數(shù)據(jù)保持一致;
隔離性: 并發(fā)訪問數(shù)據(jù)庫時(shí),一個(gè)用戶的事物不被其他事物所干擾,各并發(fā)事務(wù)之間數(shù)據(jù)庫是獨(dú)立的;
持久性: 一個(gè)事務(wù)被提交之后。它對數(shù)據(jù)庫中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對其有任何影響。
Spring事務(wù)管理接口介紹Spring事務(wù)管理接口:
PlatformTransactionManager: (平臺)事務(wù)管理器
TransactionDefinition: 事務(wù)定義信息(事務(wù)隔離級別、傳播行為、超時(shí)、只讀、回滾規(guī)則)
TransactionStatus: 事務(wù)運(yùn)行狀態(tài)
所謂事務(wù)管理,其實(shí)就是“按照給定的事務(wù)規(guī)則來執(zhí)行提交或者回滾操作”。
PlatformTransactionManager接口介紹
Spring并不直接管理事務(wù),而是提供了多種事務(wù)管理器 ,他們將事務(wù)管理的職責(zé)委托給Hibernate或者JTA等持久化機(jī)制所提供的相關(guān)平臺框架的事務(wù)來實(shí)現(xiàn)。 Spring事務(wù)管理器的接口是: org.springframework.transaction.PlatformTransactionManager ,通過這個(gè)接口,Spring為各個(gè)平臺如JDBC、Hibernate等都提供了對應(yīng)的事務(wù)管理器,但是具體的實(shí)現(xiàn)就是各個(gè)平臺自己的事情了。
PlatformTransactionManager接口代碼如下:PlatformTransactionManager接口中定義了三個(gè)方法:
Public interface PlatformTransactionManager()...{ // Return a currently active transaction or create a new one, according to the specified propagation behavior(根據(jù)指定的傳播行為,返回當(dāng)前活動(dòng)的事務(wù)或創(chuàng)建一個(gè)新事務(wù)。) TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; // Commit the given transaction, with regard to its status(使用事務(wù)目前的狀態(tài)提交事務(wù)) Void commit(TransactionStatus status) throws TransactionException; // Perform a rollback of the given transaction(對執(zhí)行的事務(wù)進(jìn)行回滾) Void rollback(TransactionStatus status) throws TransactionException; }
我們剛剛也說了Spring中PlatformTransactionManager根據(jù)不同持久層框架所對應(yīng)的接口實(shí)現(xiàn)類,幾個(gè)比較常見的如下圖所示
比如我們在使用JDBC或者iBatis(就是Mybatis)進(jìn)行數(shù)據(jù)持久化操作時(shí),我們的xml配置通常如下:
TransactionDefinition接口介紹
事務(wù)管理器接口 PlatformTransactionManager 通過 getTransaction(TransactionDefinition definition) 方法來得到一個(gè)事務(wù),這個(gè)方法里面的參數(shù)是 TransactionDefinition類 ,這個(gè)類就定義了一些基本的事務(wù)屬性。
那么什么是事務(wù)屬性呢?
事務(wù)屬性可以理解成事務(wù)的一些基本配置,描述了事務(wù)策略如何應(yīng)用到方法上。事務(wù)屬性包含了5個(gè)方面。
TransactionDefinition接口中定義了5個(gè)方法以及一些表示事務(wù)屬性的常量比如隔離級別、傳播行為等等的常量。
我下面只是列出了TransactionDefinition接口中的方法而沒有給出接口中定義的常量,該接口中的常量信息會(huì)在后面依次介紹到。
public interface TransactionDefinition { // 返回事務(wù)的傳播行為 int getPropagationBehavior(); // 返回事務(wù)的隔離級別,事務(wù)管理器根據(jù)它來控制另外一個(gè)事務(wù)可以看到本事務(wù)內(nèi)的哪些數(shù)據(jù) int getIsolationLevel(); // 返回事務(wù)必須在多少秒內(nèi)完成 //返回事務(wù)的名字 String getName(); int getTimeout(); // 返回是否優(yōu)化為只讀事務(wù)。 boolean isReadOnly(); }(1)事務(wù)隔離級別(定義了一個(gè)事務(wù)可能受其他并發(fā)事務(wù)影響的程度):
我們先來看一下 并發(fā)事務(wù)帶來的問題 ,然后再來介紹一下 TransactionDefinition 接口 中定義了五個(gè)表示隔離級別的常量。
并發(fā)事務(wù)帶來的問題
在典型的應(yīng)用程序中,多個(gè)事務(wù)并發(fā)運(yùn)行,經(jīng)常會(huì)操作相同的數(shù)據(jù)來完成各自的任務(wù)(多個(gè)用戶對統(tǒng)一數(shù)據(jù)進(jìn)行操作)。并發(fā)雖然是必須的,但可能會(huì)導(dǎo)致一下的問題。
臟讀(Dirty read): 當(dāng)一個(gè)事務(wù)正在訪問數(shù)據(jù)并且對數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時(shí)另外一個(gè)事務(wù)也訪問了這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。因?yàn)檫@個(gè)數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個(gè)事務(wù)讀到的這個(gè)數(shù)據(jù)是“臟數(shù)據(jù)”,依據(jù)“臟數(shù)據(jù)”所做的操作可能是不正確的。
丟失修改(Lost to modify): 指在一個(gè)事務(wù)讀取一個(gè)數(shù)據(jù)時(shí),另外一個(gè)事務(wù)也訪問了該數(shù)據(jù),那么在第一個(gè)事務(wù)中修改了這個(gè)數(shù)據(jù)后,第二個(gè)事務(wù)也修改了這個(gè)數(shù)據(jù)。這樣第一個(gè)事務(wù)內(nèi)的修改結(jié)果就被丟失,因此稱為丟失修改。
例如:事務(wù)1讀取某表中的數(shù)據(jù)A=20,事務(wù)2也讀取A=20,事務(wù)1修改A=A-1,事務(wù)2也修改A=A-1,最終結(jié)果A=19,事務(wù)1的修改被丟失。
不可重復(fù)讀(Unrepeatableread): 指在一個(gè)事務(wù)內(nèi)多次讀同一數(shù)據(jù)。在這個(gè)事務(wù)還沒有結(jié)束時(shí),另一個(gè)事務(wù)也訪問該數(shù)據(jù)。那么,在第一個(gè)事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個(gè)事務(wù)的修改導(dǎo)致第一個(gè)事務(wù)兩次讀取的數(shù)據(jù)可能不太一樣。這就發(fā)生了在一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的情況,因此稱為不可重復(fù)讀。
幻讀(Phantom read): 幻讀與不可重復(fù)讀類似。它發(fā)生在一個(gè)事務(wù)(T1)讀取了幾行數(shù)據(jù),接著另一個(gè)并發(fā)事務(wù)(T2)插入了一些數(shù)據(jù)時(shí)。在隨后的查詢中,第一個(gè)事務(wù)(T1)就會(huì)發(fā)現(xiàn)多了一些原本不存在的記錄,就好像發(fā)生了幻覺一樣,所以稱為幻讀。
不可重復(fù)度和幻讀區(qū)別:
不可重復(fù)讀的重點(diǎn)是修改,幻讀的重點(diǎn)在于新增或者刪除。
例1(同樣的條件, 你讀取過的數(shù)據(jù), 再次讀取出來發(fā)現(xiàn)值不一樣了 ):事務(wù)1中的A先生讀取自己的工資為 1000的操作還沒完成,事務(wù)2中的B先生就修改了A的工資為2000,導(dǎo) 致A再讀自己的工資時(shí)工資變?yōu)? 2000;這就是不可重復(fù)讀。
例2(同樣的條件, 第1次和第2次讀出來的記錄數(shù)不一樣 ):假某工資單表中工資大于3000的有4人,事務(wù)1讀取了所有工資大于3000的人,共查到4條記錄,這時(shí)事務(wù)2 又插入了一條工資大于3000的記錄,事務(wù)1再次讀取時(shí)查到的記錄就變?yōu)榱?條,這樣就導(dǎo)致了幻讀。
隔離級別
TransactionDefinition 接口中定義了五個(gè)表示隔離級別的常量:
TransactionDefinition.ISOLATION_DEFAULT: 使用后端數(shù)據(jù)庫默認(rèn)的隔離級別,Mysql 默認(rèn)采用的 REPEATABLE_READ隔離級別 Oracle 默認(rèn)采用的 READ_COMMITTED隔離級別.
TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔離級別,允許讀取尚未提交的數(shù)據(jù)變更,可能會(huì)導(dǎo)致臟讀、幻讀或不可重復(fù)讀
TransactionDefinition.ISOLATION_READ_COMMITTED: 允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù),可以阻止臟讀,但是幻讀或不可重復(fù)讀仍有可能發(fā)生
TransactionDefinition.ISOLATION_REPEATABLE_READ: 對同一字段的多次讀取結(jié)果都是一致的,除非數(shù)據(jù)是被本身事務(wù)自己所修改,可以阻止臟讀和不可重復(fù)讀,但幻讀仍有可能發(fā)生。
TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔離級別,完全服從ACID的隔離級別。所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說,該級別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會(huì)用到該級別。
是不是感覺腦細(xì)胞不夠用了,橋本奈奈未了解一下~~~顏值逆天好嗎?。?!(2)事務(wù)傳播行為(為了解決業(yè)務(wù)層方法之間互相調(diào)用的事務(wù)問題):
當(dāng)事務(wù)方法被另一個(gè)事務(wù)方法調(diào)用時(shí),必須指定事務(wù)應(yīng)該如何傳播。例如:方法可能繼續(xù)在現(xiàn)有事務(wù)中運(yùn)行,也可能開啟一個(gè)新事務(wù),并在自己的事務(wù)中運(yùn)行。在TransactionDefinition定義中包括了如下幾個(gè)表示傳播行為的常量:
支持當(dāng)前事務(wù)的情況:
TransactionDefinition.PROPAGATION_REQUIRED: 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。
TransactionDefinition.PROPAGATION_SUPPORTS: 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
TransactionDefinition.PROPAGATION_MANDATORY: 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。
不支持當(dāng)前事務(wù)的情況:
TransactionDefinition.PROPAGATION_REQUIRES_NEW: 創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
TransactionDefinition.PROPAGATION_NEVER: 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
其他情況:
TransactionDefinition.PROPAGATION_NESTED: 如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;如果當(dāng)前沒有事務(wù),則該取值等價(jià)于TransactionDefinition.PROPAGATION_REQUIRED。
這里需要指出的是,前面的六種事務(wù)傳播行為是 Spring 從 EJB 中引入的,他們共享相同的概念。而 PROPAGATION_NESTED 是 Spring 所特有的。以 PROPAGATION_NESTED 啟動(dòng)的事務(wù)內(nèi)嵌于外部事務(wù)中(如果存在外部事務(wù)的話),此時(shí),內(nèi)嵌事務(wù)并不是一個(gè)獨(dú)立的事務(wù),它依賴于外部事務(wù)的存在,只有通過外部的事務(wù)提交,才能引起內(nèi)部事務(wù)的提交,嵌套的子事務(wù)不能多帶帶提交。如果熟悉 JDBC 中的保存點(diǎn)(SavePoint)的概念,那嵌套事務(wù)就很容易理解了,其實(shí)嵌套的子事務(wù)就是保存點(diǎn)的一個(gè)應(yīng)用,一個(gè)事務(wù)中可以包括多個(gè)保存點(diǎn),每一個(gè)嵌套子事務(wù)。另外,外部事務(wù)的回滾也會(huì)導(dǎo)致嵌套子事務(wù)的回滾。
(3) 事務(wù)超時(shí)屬性(一個(gè)事務(wù)允許執(zhí)行的最長時(shí)間)所謂事務(wù)超時(shí),就是指一個(gè)事務(wù)所允許執(zhí)行的最長時(shí)間,如果超過該時(shí)間限制但事務(wù)還沒有完成,則自動(dòng)回滾事務(wù)。在 TransactionDefinition 中以 int 的值來表示超時(shí)時(shí)間,其單位是秒。
(4) 事務(wù)只讀屬性(對事物資源是否執(zhí)行只讀操作)事務(wù)的只讀屬性是指,對事務(wù)性資源進(jìn)行只讀操作或者是讀寫操作。所謂事務(wù)性資源就是指那些被事務(wù)管理的資源,比如數(shù)據(jù)源、 JMS 資源,以及自定義的事務(wù)性資源等等。如果確定只對事務(wù)性資源進(jìn)行只讀操作,那么我們可以將事務(wù)標(biāo)志為只讀的,以提高事務(wù)處理的性能。在 TransactionDefinition 中以 boolean 類型來表示該事務(wù)是否只讀。
(5) 回滾規(guī)則(定義事務(wù)回滾規(guī)則)這些規(guī)則定義了哪些異常會(huì)導(dǎo)致事務(wù)回滾而哪些不會(huì)。默認(rèn)情況下,事務(wù)只有遇到運(yùn)行期異常時(shí)才會(huì)回滾,而在遇到檢查型異常時(shí)不會(huì)回滾(這一行為與EJB的回滾行為是一致的)。
但是你可以聲明事務(wù)在遇到特定的檢查型異常時(shí)像遇到運(yùn)行期異常那樣回滾。同樣,你還可以聲明事務(wù)遇到特定的異常不回滾,即使這些異常是運(yùn)行期異常。
TransactionStatus接口介紹
TransactionStatus接口用來記錄事務(wù)的狀態(tài) 該接口定義了一組方法,用來獲取或判斷事務(wù)的相應(yīng)狀態(tài)信息.
PlatformTransactionManager.getTransaction(…) 方法返回一個(gè) TransactionStatus 對象。返回的TransactionStatus 對象可能代表一個(gè)新的或已經(jīng)存在的事務(wù)(如果在當(dāng)前調(diào)用堆棧有一個(gè)符合條件的事務(wù))。
TransactionStatus接口接口內(nèi)容如下:
public interface TransactionStatus{ boolean isNewTransaction(); // 是否是新的事物 boolean hasSavepoint(); // 是否有恢復(fù)點(diǎn) void setRollbackOnly(); // 設(shè)置為只回滾 boolean isRollbackOnly(); // 是否為只回滾 boolean isCompleted; // 是否已完成 }
由于篇幅有限,我將在下一篇文章通過轉(zhuǎn)賬實(shí)例介紹Spring編程式和聲明式事務(wù)。
歡迎關(guān)注我的微信公眾號: "Java面試通關(guān)手冊" (一個(gè)有溫度的微信公眾號,期待與你共同進(jìn)步~~~堅(jiān)持原創(chuàng),分享美文,分享各種Java學(xué)習(xí)資源):
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/69459.html
摘要:基于和命名空間的聲明式事務(wù)管理目前推薦的方式,其最大特點(diǎn)是與結(jié)合緊密,可以充分利用切點(diǎn)表達(dá)式的強(qiáng)大支持,使得管理事務(wù)更加靈活?;诘娜⒔夥绞綄⒙暶魇绞聞?wù)管理簡化到了極致。 Java面試通關(guān)手冊(Java學(xué)習(xí)指南):https://github.com/Snailclimb/Java_Guide 歷史回顧:可能是最漂亮的Spring事務(wù)管理詳解 Spring事務(wù)管理 Spring支持兩...
摘要:工廠模式的分類簡單工廠模式,又稱靜態(tài)工廠方法模式。工廠方法模式,又稱多態(tài)性工廠模式或虛擬構(gòu)造子模式抽象工廠模式,又稱工具箱或模式。具體產(chǎn)品角色抽象工廠模式所創(chuàng)建的任何產(chǎn)品對象都是某一個(gè)具體產(chǎn)品類的實(shí)例。 Java面試通關(guān)手冊(Java學(xué)習(xí)指南,歡迎Star,會(huì)一直完善下去,歡迎建議和指導(dǎo)):https://github.com/Snailclimb/Java_Guide 歷史回顧: 深...
摘要:請注意,我們在聊聊單元測試遇到問題多思考多查閱多驗(yàn)證,方能有所得,再勤快點(diǎn)樂于分享,才能寫出好文章。單元測試是指對軟件中的最小可測試單元進(jìn)行檢查和驗(yàn)證。 JAVA容器-自問自答學(xué)HashMap 這次我和大家一起學(xué)習(xí)HashMap,HashMap我們在工作中經(jīng)常會(huì)使用,而且面試中也很頻繁會(huì)問到,因?yàn)樗锩嫣N(yùn)含著很多知識點(diǎn),可以很好的考察個(gè)人基礎(chǔ)。但一個(gè)這么重要的東西,我為什么沒有在一開始...
摘要:一使用線程池的好處線程池提供了一種限制和管理資源包括執(zhí)行一個(gè)任務(wù)。每個(gè)線程池還維護(hù)一些基本統(tǒng)計(jì)信息,例如已完成任務(wù)的數(shù)量。通過重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗。使用無界隊(duì)列作為線程池的工作隊(duì)列會(huì)對線程池帶來的影響與相同。 歷史優(yōu)質(zhì)文章推薦: Java并發(fā)編程指南專欄 分布式系統(tǒng)的經(jīng)典基礎(chǔ)理論 可能是最漂亮的Spring事務(wù)管理詳解 面試中關(guān)于Java虛擬機(jī)(jvm)的問...
摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進(jìn)階面試問題列表 -...
閱讀 3246·2021-11-08 13:18
閱讀 1387·2021-10-09 09:57
閱讀 1223·2021-09-22 15:33
閱讀 4058·2021-08-17 10:12
閱讀 5114·2021-08-16 11:02
閱讀 2715·2019-08-30 10:56
閱讀 1005·2019-08-29 18:31
閱讀 3284·2019-08-29 16:30