Spring 事務傳播特性和隔離級別

Spring 事務傳播特性和隔離級別

事務是處理邏輯原子性的保證,作為單個邏輯單元執行一系列操作,要么執行完成要么全部不執行。事務遵循ACID四個特性。
事務的兩個重要特性是,事務的傳播特性和事務的隔離級別特性。傳播級別決定了事務的控制范圍,事務隔離級別決定了事務在數據庫讀寫方面的控制范圍。

  • 原子性:事務作為一個原子整體,要么執行要么完全不執行
  • 一致性:事務保證數據庫狀態從一個一致性變為另一個一致性
  • 隔離性:一個事務的執行不影響其他事務的執行
  • 持久性:已經提交事務對數據的修改,應該永久保存在數據庫

事務的傳播級別

  1. PROPAGATION_REQUIRED:Spring的默認傳播級別,如果上下文中存在事務則加入當前事務,如果不存在事務則新建事務執行。
  2. PROPAGATION_SUPPORTS:如果上下文中存在事務則加入當前事務,如果沒有事務則以非事務方式執行。
  3. PROPAGATION_MANDATORY:該傳播級別要求上下文中必須存在事務,否則拋出異常。
  4. PROPAGATION_REQUIRES_NEW:該傳播級別每次執行都會創建新事務,并同時將上下文中的事務掛起,執行完當前線程后再恢復上下文中事務。(子事務的執行結果不影響父事務的執行和回滾)
  5. PROPAGATION_NOT_SUPPORTED:當上下文中有事務則掛起當前事務,執行完當前邏輯后再恢復上下文事務。(降低事務大小,將非核心的執行邏輯包裹執行。)
  6. PROPAGATION_NEVER:該傳播級別要求上下文中不能存在事務,否則拋出異常。
  7. PROPAGATION_NESTED:嵌套事務,如果上下文中存在事務則嵌套執行,如果不存在則新建事務。(save point概念)

事務隔離級別

  • 臟讀:讀取到了別的事務回滾前的數據,例如B事務修改數據庫X,在未提交前A事務讀取了X的值,而B事務發生了回滾。
  • 不可重復讀:一個事務在兩次讀取同一個數據的值不一致。例如A事務讀取X,在中間過程中B事務修改了X的值,事務A再次讀取X時值發生了改變。
  • 幻讀:查詢得到的數據條數發生了改變,例如A事務搜索數據時有10條數據,在這時B事務插入了一條數據,A事務再搜索時發現數據有11條了。

數據隔離級別

  1. read-uncommitted:未提交讀(臟讀、不可重復讀、幻讀)
  2. read-committed:已提交讀(不可重復讀、幻讀),大多數主流數據庫的默認事務等級,保證了一個事務不會讀到另一個并行事務已修改但未提交的數據,避免了“臟讀取”。
  3. repeatable-read:可重復讀(幻讀),保證了一個事務不會修改已經由另一個事務讀取但未提交(回滾)的數據。
  4. serializable:串行化最嚴格的級別,事務串行執行,資源消耗最大

Spring事務傳播和隔離級別配置

@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,timeout=1,isolation=Isolation.DEFAULT)

  1. 事務的傳播性:@Transactional(propagation=Propagation.REQUIRED) 如果有事務, 那么加入事務, 沒有的話新建一個(默認情況下)
  2. 事務的超時性:@Transactional(timeout=30) //默認是30秒
  3. 事務的隔離級別:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
  4. 回滾:指定異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
  5. 只讀:@Transactional(readOnly=true)該屬性用于設置當前事務是否為只讀事務,設置為true表示只讀

深入理解事務隔離

未提交讀(Read uncommitted)

未提交讀(READ UNCOMMITTED)是最低的隔離級別。通過名字我們就可以知道,在這種事務隔離級別下,一個事務可以讀到另外一個事務未提交的數據。

未提交讀的數據庫鎖情況(實現原理)

事務在讀數據的時候并未對數據加鎖。

務在修改數據的時候只對數據增加[行級共享鎖]。

現象:

事務1 讀取某行記錄時,事務2也能對這行記錄進行讀取、更新(因為事務一并未對數據增加任何鎖)

事務2 對該記錄進行更新時,事務1再次讀取該記錄,能讀到事務2對該記錄的修改版本(因為事務二只增加了共享讀鎖,事務一可以再增加共享讀鎖讀取數據),即使該修改尚未被提交。

事務1 更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。(因為事務一對數據增加了共享讀鎖,事務二不能增加[排他寫鎖]進行數據的修改)

舉例

下面還是借用我在[數據庫的讀現象淺析]一文中舉的例子來說明在未提交讀的隔離級別中兩個事務之間的隔離情況。
image.png

事務一共查詢了兩次,在兩次查詢的過程中,事務二對數據進行了修改,并未提交(commit)。但是事務一的第二次查詢查到了事務二的修改結果。在數據庫的讀現象淺析中我們介紹過,這種現象我們稱之為[臟讀]。
所以,未提交讀會導致[臟讀]

提交讀(Read committed)

提交讀(READ COMMITTED)也可以翻譯成讀已提交,通過名字也可以分析出,在一個事務修改數據過程中,如果事務還沒提交,其他事務不能讀該數據。

提交讀的數據庫鎖情況

事務對當前被讀取的數據加 行級共享鎖(當讀到時才加鎖),一旦讀完該行,立即釋放該行級共享鎖;

事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

現象:

事務1在讀取某行記錄的整個過程中,事務2都可以對該行記錄進行讀取(因為事務一對該行記錄增加行級共享鎖的情況下,事務二同樣可以對該數據增加共享鎖來讀數據)。

事務1讀取某行的一瞬間,事務2不能修改該行數據,但是,只要事務1讀取完改行數據,事務2就可以對該行數據進行修改。(事務一在讀取的一瞬間會對數據增加共享鎖,任何其他事務都不能對該行數據增加排他鎖。但是事務一只要讀完該行數據,就會釋放行級共享鎖,一旦鎖釋放,事務二就可以對數據增加排他鎖并修改數據)

事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。(事務一在更新數據的時候,會對該行數據增加排他鎖,知道事務結束才會釋放鎖,所以,在事務二沒有提交之前,事務一都能不對數據增加共享鎖進行數據的讀取。所以,提交讀可以解決臟讀 的現象

舉例

image.png

在提交讀隔離級別中,在事務二提交之前,事務一不能讀取數據。只有在事務二提交之后,事務一才能讀數據。
但是從上面的例子中我們也看到,事務一兩次讀取的結果并不一致,所以提交讀不能解決。
簡而言之,提交讀這種隔離級別保證了讀到的任何數據都是提交的數據,避免了臟讀(dirty reads)。但是不保證事務重新讀的時候能讀到相同的數據,因為在每次數據讀完之后其他事務可以修改剛才讀到的數據。

可重復讀(Repeatable reads)

可重復讀(REPEATABLE READS),由于提交讀隔離級別會產生不可重復讀的讀現象。所以,比提交讀更高一個級別的隔離級別就可以解決不可重復讀的問題。這種隔離級別就叫可重復讀(這名字起的是不是很任性!)

可重復讀的數據庫鎖情況

事務在讀取某數據的瞬間(就是開始讀取的瞬間),必須先對其加 行級共享鎖,直到事務結束才釋放;

事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

現象

事務1在讀取某行記錄的整個過程中,事務2都可以對該行記錄進行讀取(因為事務一對該行記錄增加行級共享鎖的情況下,事務二同樣可以對該數據增加共享鎖來讀數據)。

事務1在讀取某行記錄的整個過程中,事務2都不能修改該行數據(事務一在讀取的整個過程會對數據增加共享鎖,直到事務提交才會釋放鎖,所以整個過程中,任何其他事務都不能對該行數據增加排他鎖。所以,可重復讀能夠解決不可重復讀的讀現象

事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。(事務一在更新數據的時候,會對該行數據增加排他鎖,知道事務結束才會釋放鎖,所以,在事務二沒有提交之前,事務一都能不對數據增加共享鎖進行數據的讀取。所以,提交讀可以解決臟讀的現象

舉例

image.png

在上面的例子中,只有在事務一提交之后,事務二才能更改該行數據。所以,只要在事務一從開始到結束的這段時間內,無論他讀取該行數據多少次,結果都是一樣的。
從上面的例子中我們可以得到結論:可重復讀隔離級別可以解決不可重復讀的讀現象。但是可重復讀這種隔離級別中,還有另外一種讀現象他解決不了,那就是[幻讀]。看下面的例子:

image.png

上面的兩個事務執行情況及現象如下:

  1. 事務一的第一次查詢條件是age BETWEEN 10 AND 30;如果這是有十條記錄符合條件。這時,他會給符合條件的這十條記錄增加行級共享鎖。任何其他事務無法更改這十條記錄。

  2. 事務二執行一條sql語句,語句的內容是向表中插入一條數據。因為此時沒有任何事務對表增加[表級鎖],所以,該操作可以順利執行。

  3. 事務一再次執行SELECT * FROM users WHERE age BETWEEN 10 AND 30;時,結果返回的記錄變成了十一條,比剛剛增加了一條,增加的這條正是事務二剛剛插入的那條。
    所以,事務一的兩次范圍查詢結果并不相同。這也就是我們提到的幻讀。

可序列化(Serializable)是最高的隔離級別,前面提到的所有的隔離級別都無法解決的幻讀,在可序列化的隔離級別中可以解決。
我們說過,產生幻讀的原因是事務一在進行范圍查詢的時候沒有增加范圍鎖(range-locks:給SELECT 的查詢中使用一個“WHERE”子句描述范圍加鎖),所以導致幻讀。

可序列化的數據庫鎖情況

事務在讀取數據時,必須先對其加 表級共享鎖 ,直到事務結束才釋放;

事務在更新數據時,必須先對其加 表級排他鎖 ,直到事務結束才釋放。

現象:

事務1正在讀取A表中的記錄時,則事務2也能讀取A表,但不能對A表做更新、新增、刪除,直到事務1結束。(因為事務一對表增加了表級共享鎖,其他事務只能增加共享鎖讀取數據,不能進行其他任何操作)

事務1正在更新A表中的記錄時,則事務2不能讀取A表的任意記錄,更不可能對A表做更新、新增、刪除,直到事務1結束。(事務一對表增加了表級排他鎖,其他事務不能對表增加共享鎖或排他鎖,也就無法進行任何操作)

雖然可序列化解決了臟讀、不可重復讀、幻讀等讀現象。但是序列化事務會產生以下效果:

  1. 無法讀取其它事務已修改但未提交的記錄。
  2. 在當前事務完成之前,其它事務不能修改目前事務已讀取的記錄。
  3. 在當前事務完成之前,其它事務所插入的新記錄,其索引鍵值不能在當前事務的任何語句所讀取的索引鍵范圍中。

四種事務隔離級別從隔離程度上越來越高,但同時在并發性上也就越來越低。之所以有這么幾種隔離級別,就是為了方便開發人員在開發過程中根據業務需要選擇最合適的隔離級別。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容

  • 事務的幾種傳播特性 PROPAGATION_REQUIRED: 如果存在一個事務,則支持當前事務。如果沒有事務則開...
    javady閱讀 2,556評論 0 5
  • 事務的嵌套概念 所謂事務的嵌套就是兩個事務方法之間相互調用。spring事務開啟 ,或者是基于接口的或者是基于類的...
    jackcooper閱讀 1,437評論 0 10
  • 很多人喜歡這篇文章,特此同步過來 由淺入深談論spring事務 前言 這篇其實也要歸納到《常識》系列中,但這重點又...
    碼農戲碼閱讀 4,760評論 2 59
  • Spring 事務屬性分析 事務管理對于企業應用而言至關重要。它保證了用戶的每一次操作都是可靠的,即便出現了異常的...
    壹點零閱讀 1,311評論 0 2
  • 22歲 ,本該是風華正茂的年紀,褪去了青春的稚嫩,帶著成熟少女的優雅知性,一定是很多宅男喜歡追逐的對象,...
    失眠的考拉閱讀 420評論 1 1