目前JavaWeb系統(tǒng)的框架容器基本都是使用Spring管理的,其中事務(wù)管理也是比較重要的,之前也是看過,網(wǎng)上介紹的文章也很多,但畢竟不是自己的,也借此機(jī)會(huì)總結(jié)下Spring對事務(wù)的管理,希望對大家有用。
1.事務(wù)基礎(chǔ)
1.1.事務(wù)的基本概念
數(shù)據(jù)庫事務(wù)(Database Transaction):是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作,要么完全地執(zhí)行,要么完全地不執(zhí)行。 “一榮俱榮,一損俱損”最能體現(xiàn)事務(wù)的的思想。也就是這些操作要么所有執(zhí)行成功,所有執(zhí)行失敗。
數(shù)據(jù)庫事務(wù)需要滿足4個(gè)特性:原子性(Atomic),一致性(Consistency),隔離性(Isolation),持久性(Durabiliy),簡稱為ACID原則。
- 原子性:表示組成一個(gè)事務(wù)的多個(gè)數(shù)據(jù)庫操作是一個(gè)不可分割的原子單元,只有所有的操作執(zhí)行成功,整個(gè)事務(wù)才能提交,若事務(wù)中的任務(wù)一個(gè)數(shù)據(jù)庫操作失敗,已經(jīng)執(zhí)行的任務(wù)操作都必須撤銷,讓數(shù)據(jù)庫返回到初始狀態(tài)。
- 一致性:事務(wù)操作成功后,數(shù)據(jù)庫所處的狀態(tài)和它的業(yè)務(wù)規(guī)則是一致的,即數(shù)據(jù)不會(huì)被破壞。如在上超市買東西付款時(shí),從你的賬戶扣錢,超市的賬戶價(jià)錢,但不管操作是否成功,你和超市的存款總額應(yīng)是不變的。
- 隔離性:在并發(fā)數(shù)據(jù)操作時(shí),不同的事務(wù)擁有各自的數(shù)據(jù)空間,它們的操作不會(huì)對對方產(chǎn)生干擾。說白了就是同時(shí)存在兩個(gè)事務(wù)一起操作數(shù)據(jù)時(shí),都會(huì)在各自的事務(wù)空間中,對數(shù)據(jù)的操作不會(huì)對對方產(chǎn)生干擾。但,各個(gè)數(shù)據(jù)庫實(shí)現(xiàn)也沒有做到完全無干擾,數(shù)據(jù)庫規(guī)定了多種事務(wù)隔離級別,不同隔離級別對應(yīng)不同的干擾程度,隔離級別越高,數(shù)據(jù)一致性越好,但并發(fā)性越弱。
- 持久性:一旦事務(wù)提交成功后,事務(wù)中所有的數(shù)據(jù)操作都必須持久化到數(shù)據(jù)庫中,即使提交事務(wù)后,數(shù)據(jù)庫馬上崩潰,在數(shù)據(jù)庫重啟時(shí),也必須能保證通過某種機(jī)制恢復(fù)數(shù)據(jù)。
上面這些特性,數(shù)據(jù)的“一致性”是最終目標(biāo),其他特性都是為他服務(wù)。
1.2.事務(wù)并發(fā)帶來的問題
同一時(shí)刻有可能有多個(gè)事務(wù)訪問數(shù)據(jù)庫的同一個(gè)資源,如果沒有采取必要的隔離措施,就會(huì)導(dǎo)致各種并發(fā)問題,破壞數(shù)據(jù)的完整性。總共包括5類,3種數(shù)據(jù)讀取問題(臟讀、不可重復(fù)讀和幻象讀)以及2類數(shù)據(jù)更新問題(第一類丟失更新和第二類丟失更新),下面分別說下
-
臟讀(dirty read)
事務(wù)A讀取事務(wù)B尚未提交的更改數(shù)據(jù),并在這個(gè)數(shù)據(jù)的基礎(chǔ)上操作。如果這時(shí)正好事務(wù)B回滾了,那么事務(wù)A讀取到數(shù)據(jù)就是臟數(shù)據(jù),也即是臟讀。
時(shí)間 | 轉(zhuǎn)賬事務(wù)A | 取款事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為1000元 | |
T4 | 取出500元把余額改為500元 | |
T5 | 查詢賬戶余額為500元(臟讀) | |
T6 | 撤銷事務(wù)余額恢復(fù)為1000元 | |
T7 | 匯入100元把余額改為600元 | |
T8 | 提交事務(wù) |
臟讀對Oracle中不會(huì)發(fā)生,因?yàn)镺racle數(shù)據(jù)庫使用了數(shù)據(jù)庫版本的機(jī)制,在回滾段為數(shù)據(jù)的每個(gè)變化都保存一個(gè)版本,使數(shù)據(jù)的更改不影響數(shù)據(jù)的讀取。
-
不可重復(fù)度(unrepeatable read)
不可重復(fù)讀是指事務(wù)A讀取了事務(wù)B已經(jīng)提交的更改數(shù)據(jù)。如A在取款事務(wù)的過程中,B往改賬戶轉(zhuǎn)賬100元,A兩次讀取的賬戶余額發(fā)生不一致。
時(shí)間 | 取款事務(wù)A | 轉(zhuǎn)賬事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為1000元 | |
T4 | 查詢賬戶余額為1000元 | |
T5 | 取出100元把余額改為900 | |
T6 | 提交事務(wù) | |
T7 | 查詢賬戶余額為900元和T4讀取的不一致 |
-
幻象讀(phantom read)
幻象讀和不可重復(fù)度類似,即事務(wù)A讀取事務(wù)B提交的新增數(shù)據(jù),這時(shí)事務(wù)A將出現(xiàn)幻象讀的問題。幻象讀一般發(fā)生在計(jì)算統(tǒng)計(jì)數(shù)據(jù)的事務(wù)中,如:銀行系統(tǒng)在同一個(gè)事務(wù)中,兩次統(tǒng)計(jì)存款賬戶的總金額,在兩次統(tǒng)計(jì)過程中,剛好新增了一個(gè)存款賬戶,并存入100元,這時(shí),兩次統(tǒng)計(jì)的總金額將不一致。
時(shí)間 | 統(tǒng)計(jì)金額事務(wù)A | 轉(zhuǎn)賬事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 統(tǒng)計(jì)總存款數(shù)為1000元 | |
T4 | 新增一個(gè)存款賬戶,存款為100元 | |
T5 | 提交事務(wù) | |
T6 | 再次統(tǒng)計(jì)存款數(shù)為1100元(幻象讀) |
-
不可重復(fù)讀和幻象讀的區(qū)別
不可重復(fù)讀在于記錄的值,即讀取到其他已經(jīng)提交事務(wù)的更改數(shù)據(jù)。
幻象讀在于記錄的數(shù)量,即讀取到其他已經(jīng)提交事務(wù)的新增數(shù)據(jù)。
數(shù)據(jù)庫的解決方法:
解決不可重復(fù)讀——添加行級鎖
解決幻象讀——添加表級鎖
-
第一類丟失更新
事務(wù)A撤銷時(shí),把已經(jīng)提交的事務(wù)B的更新數(shù)據(jù)覆蓋了。這種錯(cuò)誤可能造成很嚴(yán)重的問題。看下面例子
時(shí)間 | 取款事務(wù)A | 轉(zhuǎn)賬事務(wù)B |
---|---|---|
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為1000元 | |
T4 | 查詢賬戶余額為1000元 | |
T5 | 匯入100元把余額改為1100元 | |
T6 | 提交事務(wù) | |
T7 | 取出100元把余額改為900元 | |
T8 | 撤銷事務(wù) | |
余額恢復(fù)為1000元(丟失更新) |
-
第二類丟失更新
事務(wù)A覆蓋事務(wù)B已經(jīng)提交的數(shù)據(jù),造成事務(wù)B所做操作丟失。
2.事務(wù)隔離級別
數(shù)據(jù)庫為了解決1.2節(jié)中描述的事務(wù)并發(fā)問題通常是使用數(shù)據(jù)庫鎖機(jī)制,但數(shù)據(jù)庫中的鎖機(jī)制用戶直接使用很麻煩,所以數(shù)據(jù)庫提供了自動(dòng)鎖機(jī)制。即用戶指定相應(yīng)的事務(wù)隔離級別,數(shù)據(jù)庫會(huì)添加合適的鎖。
ANSI/ISO SQL 92標(biāo)準(zhǔn)定義了4個(gè)等級的事務(wù)隔離級別,不同事務(wù)隔離級別能夠解決的數(shù)據(jù)并發(fā)問題的能力是不同的。如下:
隔離級別 | 臟讀 | 不可重復(fù)讀 | 幻象讀 | 第一類丟失更新 | 第二類丟失更新 |
---|---|---|---|---|---|
READ UNCOMMITED | 允許 | 允許 | 允許 | 不允許 | 允許 |
READ COMMITED | 不允許 | 允許 | 允許 | 不允許 | 允許 |
REPEATABLE READ | 不允許 | 不允許 | 允許 | 不允許 | 不允許 |
SERIALIZABLE | 不允許 | 不允許 | 不允許 | 不允許 | 不允許 |
事務(wù)的隔離級別和數(shù)據(jù)庫的并發(fā)性是對立的,兩者此增彼漲。使用READ UNCOMMITED隔離級別的數(shù)據(jù)庫擁有最高的并發(fā)性和吞吐量,使用SERIALIZABLE隔離級別的數(shù)據(jù)庫并發(fā)性和吞吐量最低。
想了解更多技術(shù)文章信息,請繼續(xù)關(guān)注wiliam.s Blog,謝謝,歡迎來訪!