数据库 - 事务管理(ACID)隔离级别 事务传播行为
轉(zhuǎn)載自? ?數(shù)據(jù)庫 - 事務(wù)管理(ACID)隔離級別 事務(wù)傳播行為
總覽:
事務(wù)的4大特性(ACID)
原子性(Atomicity)
原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾,這和前面兩篇博客介紹事務(wù)的功能是一樣的概念,因此事務(wù)的操作如果成功就必須要完全應(yīng)用到數(shù)據(jù)庫,如果操作失敗則不能對數(shù)據(jù)庫有任何影響。
一致性(Consistency)
一致性是指事務(wù)必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另一個一致性狀態(tài),也就是說一個事務(wù)執(zhí)行之前和執(zhí)行之后都必須處于一致性狀態(tài)。
拿轉(zhuǎn)賬來說,假設(shè)用戶A和用戶B兩者的錢加起來一共是5000,那么不管A和B之間如何轉(zhuǎn)賬,轉(zhuǎn)幾次賬,事務(wù)結(jié)束后兩個用戶的錢相加起來應(yīng)該還得是5000,這就是事務(wù)的一致性。
隔離性(Isolation)
隔離性是當(dāng)多個用戶并發(fā)訪問數(shù)據(jù)庫時,比如操作同一張表時,數(shù)據(jù)庫為每一個用戶開啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個并發(fā)事務(wù)之間要相互隔離。
即要達(dá)到這么一種效果:對于任意兩個并發(fā)的事務(wù)T1和T2,在事務(wù)T1看來,T2要么在T1開始之前就已經(jīng)結(jié)束,要么在T1結(jié)束之后才開始,這樣每個事務(wù)都感覺不到有其他事務(wù)在并發(fā)地執(zhí)行。
關(guān)于事務(wù)的隔離性數(shù)據(jù)庫提供了多種隔離級別,稍后會介紹到。
持久性(Durability)
持久性是指一個事務(wù)一旦被提交了,那么對數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會丟失提交事務(wù)的操作。
事務(wù)并發(fā)訪問的問題(隔離性)
臟讀
兩個事務(wù)正在并發(fā)的執(zhí)行,事實上最后結(jié)果應(yīng)該是1500才對,時間5時刻的查詢余額為0就是臟數(shù)據(jù),事務(wù)A讀取了事務(wù)B中未提交的數(shù)據(jù),這就是臟讀。
| 1 | 開始事務(wù) | - |
| 2 | - | 開始事務(wù) |
| 3 | - | 查詢余額有1000 |
| 4 | - | 取出1000,余額0 |
| 5 | 查詢余額0 | - |
| 6 | - | 撤銷掉事務(wù) |
| 7 | 存入500,余額500 | - |
| 8 | 提交事務(wù) | - |
不可重復(fù)讀
兩個事務(wù)正在并發(fā)的執(zhí)行,結(jié)果A兩次讀取的結(jié)果不一樣,這是因為兩次查詢有間隔,期間被其他事務(wù)修改并提交了事務(wù),相比臟讀的區(qū)別是,不可重復(fù)讀是讀取另一事務(wù)提交的數(shù)據(jù)。這種現(xiàn)象也是正常的,是由于事務(wù)的隔離級造成的,但是在在某些特別的情況下也是不允許的。
| 1 | 開始事務(wù) | - |
| 2 | - | 開始事務(wù) |
| 3 | - | 查詢余額有1000 |
| 4 | 查詢余額1000 | - |
| 5 | ? | 取出1000,余額0 |
| 6 | - | 提交事務(wù) |
| 7 | 查詢余額0 | - |
幻讀
兩個事務(wù)正在并發(fā)的執(zhí)行,事務(wù)A第一次統(tǒng)計和第二統(tǒng)計的結(jié)果不一樣,是因為事務(wù)B新增了一條數(shù)據(jù),和不可重復(fù)讀一樣,都是讀取了另外一個事務(wù)的數(shù)據(jù),不同的是不可重復(fù)讀查詢的是同一條數(shù)據(jù),而幻讀則是針對批量的數(shù)據(jù),或者說不可重復(fù)讀是A讀取了B的更新數(shù)據(jù),幻讀是A讀取了B的新增數(shù)據(jù)。
| 1 | 開始事務(wù) | - |
| 2 | - | 開始事務(wù) |
| 3 | 統(tǒng)計總金額10000 | - |
| 4 | - | - |
| 5 | ? | 存入100 |
| 6 | - | 提交事務(wù) |
| 7 | 統(tǒng)計總金額10100 | - |
數(shù)據(jù)庫的隔離級別(MySQL為例)
明白上面的問題之后就明白為什么需要隔離級別了,不同的隔離級別能處理不同的并發(fā)事務(wù)問題,下表:
| READ_UNCOMMITTED | 允許 | 允許 | 允許 |
| READ_COMMITTED | 禁止 | 允許 | 允許 |
| REPEATABLE_READ | 禁止 | 禁止 | 允許 |
| SERIALIZABLE | 禁止 | 禁止 | 禁止 |
MySQL默認(rèn)的事務(wù)級別是READ_COMMITTED
JDBC的數(shù)據(jù)隔離級別設(shè)置
| TRANSACTION_READ_UNCOMMITTED | ur | 就是俗稱“臟讀”(dirty read),在沒有提交數(shù)據(jù)時能夠讀到已經(jīng)更新的數(shù)據(jù) |
| TRANSACTION_READ_COMMITTED | cs | 在一個事務(wù)中進(jìn)行查詢時,允許讀取提交前的數(shù)據(jù),數(shù)據(jù)提交后,當(dāng)前查詢就可以讀取到數(shù)據(jù)。update數(shù)據(jù)時候并不鎖住表 |
| TRANSACTION_REPEATABLE_READ | rs | 在一個事務(wù)中進(jìn)行查詢時,不允許讀取其他事務(wù)update的數(shù)據(jù),允許讀取到其他事務(wù)提交的新增數(shù)據(jù) |
| TRANSACTION_SERIALIZABLE | rr | 在一個事務(wù)中進(jìn)行查詢時,不允許任何對這個查詢表的數(shù)據(jù)修改。 |
Spring的事務(wù)傳播行為
事務(wù)傳播
事務(wù)怎么傳播?方法A傳播到方法B。
Spring解決的就是方法之間的事務(wù)傳播。
下面看下每一種行為具體代表的含義:
REQUIRED
業(yè)務(wù)方法需要在一個事務(wù)中運行。如果方法運行時,已經(jīng)處在一個事務(wù)中,那么這個時候就會加入到該事務(wù)中,如果當(dāng)前沒有事務(wù)環(huán)境的話,就會為自己創(chuàng)建一個新的事務(wù)。
SUPPORTS
這一事務(wù)屬性表明,如果業(yè)務(wù)方法A在某個事務(wù)范圍內(nèi)被調(diào)用,則方法成為事務(wù)的一部分。如果業(yè)務(wù)方法在事務(wù)范圍外被調(diào)用,則方法在沒有事務(wù)的環(huán)境下執(zhí)行。即當(dāng)標(biāo)注了事務(wù)傳播屬性——SUPPORTS的業(yè)務(wù)方法在另一個bean的業(yè)務(wù)方法中執(zhí)行時,如果另一個bean的業(yè)務(wù)方法開啟了事務(wù),它就會處在事務(wù)中執(zhí)行,如果另一個bean的業(yè)務(wù)方法也沒開啟事務(wù),那么它也在沒有事務(wù)的環(huán)境中進(jìn)行。
MANDATORY
該屬性指定業(yè)務(wù)方法只能在一個已經(jīng)存在的事務(wù)中執(zhí)行,業(yè)務(wù)方法不能發(fā)起自己的事務(wù)。如果業(yè)務(wù)方法在沒有事務(wù)的環(huán)境下調(diào)用,容器就會拋出異常。一種比較強硬的方式。
REQUIRES_NEW
該屬性表明不管當(dāng)前是否存在事務(wù),業(yè)務(wù)方法總會為自己發(fā)起一個新的事務(wù)。如果方法已經(jīng)運行在一個事務(wù)中,則原有事務(wù)會被掛起,新的事務(wù)會被創(chuàng)建,直到方法執(zhí)行結(jié)束,新事務(wù)才算結(jié)束,原先的事務(wù)才會恢復(fù)執(zhí)行。
NOT_SUPPORTED
聲明方法不需要事務(wù)。如果方法沒有關(guān)聯(lián)到一個事務(wù),容器不會為它開啟事務(wù)。如果方法在一個事務(wù)中被調(diào)用(在其他業(yè)務(wù)bean的方法中被調(diào)用了,而其他業(yè)務(wù)bean的方法是開啟了事務(wù)的),該事務(wù)會被掛起,在方法調(diào)用結(jié)束后,原先的事務(wù)便會恢復(fù)執(zhí)行。
NEVER
指定業(yè)務(wù)方法絕對不能在事務(wù)范圍內(nèi)執(zhí)行。如果業(yè)務(wù)方法在某個事務(wù)中執(zhí)行,容器會拋出異常,只有業(yè)務(wù)方法沒有關(guān)聯(lián)到任何事務(wù),才能正常執(zhí)行。比較強硬的方式,就是不支持事務(wù)。
NESTED
(嵌套事務(wù))如果一個活動的事務(wù)存在,則當(dāng)前方法運行在一個嵌套的事務(wù)中。 如果沒有活動事務(wù),就創(chuàng)建一個新的事務(wù)。它使用了一個單獨的事務(wù),這個事務(wù)擁有多個可以回滾的保存點。內(nèi)部事務(wù)的回滾不會對外部事務(wù)造成影響。外部事務(wù)回滾會導(dǎo)致內(nèi)部事務(wù)的回滾。如果被調(diào)用的內(nèi)部方法沒有捕獲異常,跑出異常也會導(dǎo)致外部事務(wù)的回滾。
看下Spring中枚舉定義的7種事務(wù)傳播行為
package org.springframework.transaction.annotation;public enum Propagation {REQUIRED(0),SUPPORTS(1),MANDATORY(2),REQUIRES_NEW(3),NOT_SUPPORTED(4),NEVER(5),NESTED(6);private final int value;private Propagation(int value) {this.value = value;}public int value() {return this.value;} }在使用注解方式的事務(wù)時候我們可以用下面的方式來設(shè)置事務(wù)的傳播行為
@Transactional(propagation?= Propagation.REQUIRED)是不是很方便。
只讀事務(wù)
readOnly屬性:設(shè)置為只讀事務(wù),對于只讀事務(wù),它就不能進(jìn)行更新操作,一般只存在數(shù)據(jù)讀取的時候,可以將readOnly屬性設(shè)置為true,可提供效率。
事務(wù)超時
timeout屬性:代表事務(wù)的超時時間,默認(rèn)為30s,一般情況下都不需要設(shè)置超時時間。如果超過時間就回滾。
總結(jié)
以上是生活随笔為你收集整理的数据库 - 事务管理(ACID)隔离级别 事务传播行为的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 维修尘封已久的坏电脑竟然花了我350元电
- 下一篇: 浅谈流处理算法 (1) – 蓄水池采样