javascript
Spring事务那些事儿
(一)事務的隔離級別
- 大家都知道事務有四個屬性,即ACID(原子性、一致性、隔離性、持久性)。這四個里面稍微難理解點的是一致性和持久性。所謂的一致性是指:事務執(zhí)行前后數(shù)據(jù)的一致性狀態(tài),例如事務執(zhí)行前用戶有1萬元,事務回滾后用戶仍應該有1萬元。而這里的持久性指的是:事務在提交后結果是永久的,即使程序崩潰數(shù)據(jù)也能恢復,當然數(shù)據(jù)庫的持久性指的是高可靠性,事務執(zhí)行后數(shù)據(jù)保證一定寫到了磁盤及備份日志,但并不是指高可用性 ,如果你強行把機器的磁盤燒了,那數(shù)據(jù)也是無法恢復的。
- 在事務隔離性的基礎上,我們對事務間的相互影響程度進行定級,即事務的隔離級別。通常事務有四種隔離級別:read uncommitted、read committed、repeatable read、serializable。
(1)read uncommitted是最低的隔離級別,其實就如其英文名一樣,處于這個級別的事務可能會讀到其他事務尚未提交的數(shù)據(jù)修改,即存在臟讀問題。除此之外,還存在不可重復讀和幻讀問題問題。
(2)read committed是大部分數(shù)據(jù)庫的默認隔離級別,它解決了臟讀問題,但是仍存在不可重復讀和幻讀問題。
(3)repeatable read解決了不可重復讀的問題,但是仍可能存在幻讀的問題。值得一提的是mysql的默認級別是repeatable read,但它卻不存在幻讀問題,因為mysql通過使用next-key lock技術解決了問題,即使在repeatable read級別也能完全保證事務的隔離性要求。
(4) serializable是最為嚴格的隔離級別,所有事務順序執(zhí)行,實際上是通過將并行轉為串行來解決事務隔離問題,無疑會降低性能。
不可重復讀和幻讀的區(qū)別:
不可重復讀指在同一事務中多次查詢同一記錄(eg:select * from xx where id = 1),查詢結果不一致。這主要是由于多次讀期間其他事務update或delete了記錄。
幻讀是指在同一事務中多次進行范圍查詢(eg:select count(*) from xx where id > 1 and id < 100),查詢結果不一致。這主要是由于多次范圍查詢期間其他事務insert了新數(shù)據(jù)。
(二)事務的參與者及分類
在一般的事務場景中通常有以下幾個參與者:
我們通常會根據(jù)RM的數(shù)量將事務分為分布式事務和局部事務(本地事務)兩種。 在分布式事務中通常會存在多個不同的RM,這些RM分布在不同的系統(tǒng)中,相互之間通過TP monitor協(xié)調,利用兩階段提交來保障事務的ACID屬性。在局部事務中一般每次數(shù)據(jù)操作只有一個RM,數(shù)據(jù)操作只需操作一個數(shù)據(jù)庫,在同一個事務中不會進行多個數(shù)據(jù)庫的更新。接下來我們將著重介紹局部事務的實現(xiàn),畢竟分布式事務我懂的也不多😜。
(三)局部事務詳解
1.事務原理簡介
首先我們需要了解的很重要的一點是,spring的事務底層實現(xiàn)本質上是依賴于其使用的數(shù)據(jù)庫服務器,例如mysql數(shù)據(jù)庫。在mysql數(shù)據(jù)庫中事務的隔離依賴于mysql的鎖機制,持久性和原子依賴于redo日志,而一致性依賴于undo日志。mysql提供事務功能的具體實現(xiàn),spring負責界定事務的邊界及定義事務的傳播性,然后通過特定的數(shù)據(jù)訪問技術(例:jdbc、hibernate等)的API對事務進行管理。
我們以jdbc舉個簡單的例子,我們可以看下面的代碼:
這就是我們利用jdbc進行的最簡單的事務管理,將autoCommit置為false,然后根據(jù)各種情況進行事務的回滾提交等操作。而我們平時普通的數(shù)據(jù)操作都是默認自動提交,mysql會自動隱式的幫我們commit事務。
但是上面的寫法在實際的開發(fā)中存在很多的問題:1.不同的數(shù)數(shù)據(jù)訪問技術有不同的api、2.我們需要自己手動捕獲處理各種以sql異常、3.事務管理代碼和數(shù)據(jù)訪問代碼及業(yè)務代碼耦合在一起。
2.spring事務框架重要類
為了解決上面提到的問題,spring為我們提供了優(yōu)秀的事務框架。我們先來介紹下事務框架中重要的類:
| TransactionDefinition | 用來定義事務屬性,包括事務的隔離性、傳播性、超時時間、是否只讀等屬性。 |
| TransactionStatus | 用來記錄事務開啟到事務結束期間事務的狀態(tài),這個類一般在編程式事務中使用。 |
| PlatformTransactionManager | spring事務框架的核心類,負責事務的管理,包括事務的commit、rollback等。 |
3.spring事務傳播性
| REQUIRED | 業(yè)務方法需要在一個事務中運行,如果方法運行時,已處在一個事務中,那么就加入該事務,否則自己創(chuàng)建一個新的事務,這是spring默認的傳播行為。 |
| SUPPORTS | 如果業(yè)務方法在某個事務范圍內被調用,則方法成為該事務的一部分,如果業(yè)務方法在事務范圍外被調用,則方法在沒有事務的環(huán)境下執(zhí)行。 |
| MANDATORY | 只能在一個已存在事務中執(zhí)行,業(yè)務方法不能發(fā)起自己的事務,如果業(yè)務方法在沒有事務的環(huán)境下調用,就拋異常。 |
| REQUIRES_NEW | 業(yè)務方法總是會為自己發(fā)起一個新的事務,如果方法已運行在一個事務中,則原有事務被掛起,新的事務被創(chuàng)建,直到方法結束,新事務才結束,原先的事務才會恢復執(zhí)行。 |
| NOT_SUPPORTED | 聲明方法需要事務,如果方法沒有關聯(lián)到一個事務,容器不會為它開啟事務。如果方法在一個事務中被調用,該事務會被掛起,在方法調用結束后,原先的事務便會恢復執(zhí)行。 |
| NEVER | 聲明方法絕對不能在事務范圍內執(zhí)行,如果方法在某個事務范圍內執(zhí)行,容器就拋異常。只有沒關聯(lián)到事務,才正常執(zhí)行。 |
| NESTED | 如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動的事務,則按REQUIRED屬性執(zhí)行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保證點。內部事務回滾不會對外部事務造成影響, 它只對DataSourceTransactionManager 事務管理器起效。 |
--------未完待續(xù),敬請期待
總結
以上是生活随笔為你收集整理的Spring事务那些事儿的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【狂神说】JVM
- 下一篇: http协议工作流程