數(shù)據(jù)庫(kù)事務(wù)

事務(wù)隔離.png

[事務(wù)簡(jiǎn)介:] https://www.cnblogs.com/caoyc/p/5632963.html

1. 事務(wù)隔離帶來(lái)的問題

更新丟失:兩事務(wù)同時(shí)更新,一個(gè)失敗回滾覆蓋另一個(gè)事務(wù)的更新?;蚴聞?wù)1執(zhí)行更細(xì)操作,在事務(wù)1結(jié)束前事務(wù)2也更新,則事務(wù)1的更細(xì)結(jié)果被事務(wù)2的覆蓋了。

臟讀:事務(wù)T2讀取到事務(wù)T1修改了但是還未提交的數(shù)據(jù),之后事務(wù)T1又回滾其更新操作,導(dǎo)致事務(wù)T2讀到的是臟數(shù)據(jù)。

不可重復(fù)讀:事務(wù)T1讀取某個(gè)數(shù)據(jù)后,事務(wù)T2對(duì)其做了修改并且提交,當(dāng)事務(wù)T1再次讀該數(shù)據(jù)時(shí)得到與前一次不同的值。

在某些情況下,不可重復(fù)讀并不是問題,比如我們多次查詢某個(gè)數(shù)據(jù)當(dāng)然以最后查詢得到的結(jié)果為主。但在另一些情況下就有可能發(fā)生問題,例如對(duì)于同一個(gè)數(shù)據(jù)A和B依次查詢就可能不同,A和B就可能打起來(lái)了

虛讀(幻讀):事務(wù)T1讀取在讀取某范圍數(shù)據(jù)時(shí),事務(wù)T2又插入一條數(shù)據(jù),當(dāng)事務(wù)T1再次數(shù)據(jù)這個(gè)范圍數(shù)據(jù)時(shí)發(fā)現(xiàn)不一樣了,出現(xiàn)了一些“幻影行”

2. 事務(wù)隔離級(jí)別(Isolation)

1. 讀未提交(Read Uncommitted)

含義解釋:只限制同一數(shù)據(jù)寫事務(wù)禁止其他寫事務(wù)。解決”更新丟失”。(一事務(wù)寫時(shí)禁止其他事務(wù)寫)
名稱解釋:可讀取未提交數(shù)據(jù)
所需的鎖:排他寫鎖
Oracle不支持此事務(wù)級(jí)別

2. 讀提交(Read Committed)

含義解釋:只限制同一數(shù)據(jù)寫事務(wù)禁止其它讀寫事務(wù)。解決”臟讀”,以及”更新丟失”。(一事務(wù)寫時(shí)禁止其他事務(wù)讀寫)
名稱解釋:必須提交以后的數(shù)據(jù)才能被讀取
所需的鎖:排他寫鎖、瞬間共享讀鎖
MVCC:快照版本是該行的最新一條快照版本

3. 可重復(fù)讀(Repeatable Read)

含義解釋:限制同一數(shù)據(jù)寫事務(wù)禁止其他讀寫事務(wù),讀事務(wù)禁止其它寫事務(wù)(允許讀)。解決”不可重復(fù)讀”,以及”更新丟失”和”臟讀”。(一事務(wù)寫時(shí)禁止其他事務(wù)讀寫、一事務(wù)讀時(shí)禁止其他事務(wù)寫)
注意沒有解決幻讀,解決幻讀的方法是增加范圍鎖(range lock)或者表鎖
名稱解釋:能夠重復(fù)讀取
所需的鎖:排他寫鎖、共享讀鎖
解惑:MySQL的InnoDB引擎在此隔離級(jí)別下,通過(guò)MVCC解決不可重復(fù)度幻讀2個(gè)問題,因此很難模擬出(不過(guò)事務(wù)內(nèi)insert重復(fù)數(shù)據(jù)的時(shí)候還是可以看到幻讀的場(chǎng)景)
MVCC:快照版本是事務(wù)開始時(shí)的版本

4. 串行化(Serializable)

含義解釋:限制所有讀寫事務(wù)都必須串行化實(shí)行。它要求事務(wù)序列化執(zhí)行,事務(wù)只能一個(gè)接著一個(gè)地執(zhí)行,但不能并發(fā)執(zhí)行。如果僅僅通過(guò)“行級(jí)鎖”是無(wú)法實(shí)現(xiàn)事務(wù)序列化的,必須通過(guò)其他機(jī)制保證新插入的數(shù)據(jù)不會(huì)被剛執(zhí)行查詢操作的事務(wù)訪問到。(一事務(wù)寫時(shí)禁止其他事務(wù)讀寫、一事務(wù)讀時(shí)禁止其他事務(wù)讀寫)
所須的鎖:范圍鎖或表鎖

事務(wù)A:讀行r | --------------- | 讀行r
事務(wù)B:--------| 寫r commit |

READ COMMITTED:讀的是事務(wù)B提交后的快照
REPEATABLE READ:讀的是事務(wù)A開始時(shí)讀的快照。

3. 事務(wù)屬性,傳播行為

1. Required(spring transaction 默認(rèn)值)

必須有邏輯事務(wù),否則新建一個(gè)事務(wù),使用PROPAGATION_REQUIRED指定,表示如果當(dāng)前存在一個(gè)邏輯事務(wù),則加入該邏輯事務(wù),否則將新建一個(gè)邏輯事務(wù)

2. RequiredNew

創(chuàng)建新的邏輯事務(wù),使用PROPAGATION_REQUIRES_NEW指定,表示每次都創(chuàng)建新的邏輯事務(wù)(物理事務(wù)也是不同的)

3. Supports

支持當(dāng)前事務(wù),使用PROPAGATION_SUPPORTS指定,指如果當(dāng)前存在邏輯事務(wù),就加入到該邏輯事務(wù),如果當(dāng)前沒有邏輯事務(wù),就以非事務(wù)方式執(zhí)行

4. NotSupported

不支持事務(wù),如果當(dāng)前存在事務(wù)則暫停該事務(wù),使用PROPAGATION_NOT_SUPPORTED指定,即以非事務(wù)方式執(zhí)行,如果當(dāng)前存在邏輯事務(wù),就把當(dāng)前事務(wù)暫停,以非事務(wù)方式執(zhí)行

5. Mandatory

必須有事務(wù),否則拋出異常,使用PROPAGATION_MANDATORY指定,使用當(dāng)前事務(wù)執(zhí)行,如果當(dāng)前沒有事務(wù),則拋出異常(IllegalTransactionStateException)。當(dāng)運(yùn)行在存在邏輯事務(wù)中則以當(dāng)前事務(wù)運(yùn)行,如果沒有運(yùn)行在事務(wù)中,則拋出異常

6. Never

不支持事務(wù),如果當(dāng)前存在是事務(wù)則拋出異常,使用PROPAGATION_NEVER指定,即以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常(IllegalTransactionStateException)

7. Nested

如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行;如果當(dāng)前沒有事務(wù),則該取值等價(jià)于TransactionDefinition.PROPAGATION_REQUIRED

Nested和RequiresNew的區(qū)別:

  • RequiresNew每次都創(chuàng)建新的獨(dú)立的物理事務(wù),而Nested只有一個(gè)物理事務(wù);
  • Nested嵌套事務(wù)回滾或提交不會(huì)導(dǎo)致外部事務(wù)回滾或提交,但外部事務(wù)回滾將導(dǎo)致嵌套事務(wù)回滾,而 RequiresNew由于都是全新的事務(wù),所以之間是無(wú)關(guān)聯(lián)的;
  • Nested使用JDBC 3的保存點(diǎn)(save point)實(shí)現(xiàn),即如果使用低版本驅(qū)動(dòng)將導(dǎo)致不支持嵌套事務(wù)

4. 事務(wù)模型

4.1 本地事務(wù)模型

使用本地資源管理器(local resource manager)進(jìn)行管理,實(shí)際上管理的連接,而不是事務(wù)
實(shí)際上由DBMSJMS提供者進(jìn)行管理

Connection conn = ds.getConnection();
conn.setAutoCommit(false);
conn.begin();
try {
  conn.commit();
} catch() {
  conn.rollback();
}

4. 2 編程事務(wù)模型

利用Java事務(wù)API(JTA)請(qǐng)求提供商提供的Java事務(wù)服務(wù)(JTS),利用javax.transaction.UserTransaction接口進(jìn)行編程事務(wù)管理,而不是連接
要注意異常的捕獲,很麻煩,而且事務(wù)沒有傳播性

UserTransaction txn = sessionCtx.getUserTransaction();
txn.begin();
try {
  txn.commit();
} catch() {
  txn.rollback();
}

4.3 聲明(容器托管)事務(wù)模型

軟件框架或則容器管理了事務(wù)的開始和結(jié)束,事務(wù)的傳播屬性,事務(wù)的隔離級(jí)別,回滾條件

@Transactional(rollbackFor = Exception.class, 
  isolation = Isolation.READ_COMMITTED, 
  propagation = Propagation.REQUIRED
)

支持隔離傳播屬性:
read設(shè)置為supports,write設(shè)置為required/mandatory,如果異常不負(fù)責(zé)回滾事務(wù),使用mandatory

REQUIRED,REQUIRED_NEW,MANDATORY
SUPPORTS,NOT_SUPPORTED,NEVER

支持隔離級(jí)別: 隔離性= 并發(fā)性+一致性

READ_UNCOMMITED,READ_COMMITED
REPEATABLE_READ,SERIALIZEABLE

Java事務(wù)服務(wù)(JTS):
異構(gòu)系統(tǒng)實(shí)現(xiàn)分布式事務(wù)交互

5 事務(wù)設(shè)計(jì)模式

5.1 客戶端擁有事務(wù)

客戶端控制 begin/commit/rollback
然后組件設(shè)置傳播mandatory
并且不處理try{}catch(){}
**不建議使用**

5.2 領(lǐng)域服務(wù)擁有事務(wù)

服務(wù)端提供每個(gè)領(lǐng)域的服務(wù),集中管理事務(wù)

5.3 服務(wù)器端代理?yè)碛惺聞?wù)

6 XA事務(wù)處理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容