您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“怎么理解事務(wù)隔離級(jí)別、MVCC、spring事物傳播屬性”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
數(shù)據(jù)庫(kù)有四種事務(wù)隔離級(jí)別
讀未提交(Read uncommitted)
讀已提交(Read committed)
可重復(fù)讀(Repeatable read)
串行化(Serializable)
以上事務(wù)隔離級(jí)別依次遞增,但是性能依次遞減。
mysql支持以上四種隔離級(jí)別,其默認(rèn)是:可重復(fù)讀(Repeatable read)。
oracle數(shù)據(jù)庫(kù)支持READ COMMITTED 和 SERIALIZABLE兩種。
oracle和PostgreSQL默認(rèn)是:讀已提交(Read committed)。
以上四種隔離分別會(huì)出現(xiàn)以下問(wèn)題
隔離級(jí)別 | 臟讀 | 不可重復(fù)讀 | 幻讀 |
---|---|---|---|
讀未提交(Read uncommitted) | 可能 | 可能 | 可能 |
讀已提交(Read committed) | 不可能 | 可能 | 可能 |
可重復(fù)讀(Repeatable read) | 不可能 | 不可能 | 可能 |
串行化(Serializable) | 不可能 | 不可能 | 不可能 |
臟讀:
T1修改數(shù)據(jù)后未提交之前,T2可以訪問(wèn)修改后的數(shù)據(jù)。
不可重復(fù)讀:
T1:讀取userid=1的salary=1000;
T2:將userid=1的salary改為2000并提交;
T1:此時(shí)再次讀取userid=1的記錄,則讀取不到salary=1000了,這既是不可重復(fù)讀。
幻讀:
T1:select id=1,resultset=null,此時(shí)準(zhǔn)備插入一條;
T2:insert id=1 并提交;
T1:insert id=1 ,報(bào)錯(cuò)。
在這種情況下,T1按照邏輯本來(lái)是預(yù)計(jì)成功的,但是卻報(bào)錯(cuò)主鍵沖突,此時(shí)T1就產(chǎn)生了幻讀,仿佛看花眼出現(xiàn)幻象了一般。
串行化:
每個(gè)事務(wù)排隊(duì)執(zhí)行。
串行話為什么不會(huì)出現(xiàn)幻讀?因?yàn)闀?huì)鎖定索引。
還是上面幻讀的例子,T1查詢的時(shí)候,因?yàn)槭侵麈I查詢,數(shù)據(jù)庫(kù)會(huì)自動(dòng)給索引加上鎖(索引加鎖,與具體數(shù)據(jù)無(wú)關(guān)),所以T2的操作會(huì)失敗,T1的插入會(huì)成功。當(dāng)然如果我們?cè)诳芍貜?fù)讀模式下,通過(guò)select for update 是也可以達(dá)到Serializable的效果。
MVCC: Mulit Vsersion Concurrent Control 即:多版本并發(fā)控制
作用:解決不可重復(fù)讀問(wèn)題(例:T1正在查詢數(shù)據(jù),T2修改了,T1在查就查不到原來(lái)的數(shù)據(jù)了)
Mysql默認(rèn)事務(wù)隔離級(jí)別是RR,MVCC可以保證在RC和RR模式下實(shí)現(xiàn)可重復(fù)讀:
每個(gè)表中會(huì)存在兩個(gè)隱藏的字段:crate_version、delete_version,這兩個(gè)字段都是用來(lái)記錄當(dāng)前的事物ID(事物ID數(shù)據(jù)庫(kù)自增)。
insert:添加數(shù)據(jù)時(shí)會(huì)記錄create_version。 delete:刪除數(shù)據(jù)時(shí)會(huì)更新delete_version。 update:更新數(shù)據(jù)時(shí)會(huì)將動(dòng)作拆分為insert+delete,即新增一條數(shù)據(jù),并且吧舊數(shù)據(jù)delete_version更改為當(dāng)前事物ID。 select:查詢數(shù)據(jù)時(shí),在滿足條件的記錄上判斷: 1.create_version小于等于當(dāng)前查詢事物的ID(并發(fā)插入不可見(jiàn)) 2.delete_version為空,或者大于當(dāng)前版本ID(并發(fā)刪除可見(jiàn))
由此看來(lái),數(shù)據(jù)的更新操作并不會(huì)影響查詢的數(shù)據(jù),實(shí)現(xiàn)了可重復(fù)讀。
PS: 由于舊數(shù)據(jù)并不會(huì)真正刪除,所以innodb會(huì)開(kāi)啟后臺(tái)線程執(zhí)行清理工作:將刪除版本號(hào)小于當(dāng)前事物ID的版本進(jìn)行清理,這個(gè)過(guò)程叫做purge。
事務(wù)傳播特性是指,當(dāng)多個(gè)方法形成一個(gè)調(diào)用鏈時(shí),事務(wù)是如何傳播的(如A方法中調(diào)用了B方法,那么事務(wù)是以哪種方式傳播給B)。
spring只提供事務(wù)管理器,其實(shí)現(xiàn)交給hibernate等其他框架;Spring定義了7中傳播行為(org.springframework.transaction包中的TransactionDefinition接口):
PROPAGATION_REQUIRED(spring默認(rèn)):如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。
PROPAGATION_SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
PROPAGATION_MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則拋出異常。
PROPAGATIONREQUIRESNEW:創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
PROPAGATIONNOTSUPPORTED:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
PROPAGATION_NEVER:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
PROPAGATIONNESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行;如果當(dāng)前沒(méi)有事務(wù),則該取值等價(jià)于PROPAGATIONREQUIRED。
以上七中傳播特性中,前六種屬于EJB,被spring引進(jìn);后一種是spring特有的。
ISOLATION_DEFAULT:使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別。
ISOLATION_READ_UNCOMMITTED:允許讀取尚未提交的更改。可能導(dǎo)致臟讀、幻影讀或不可重復(fù)讀。
ISOLATION_READ_COMMITTED:允許從已經(jīng)提交的并發(fā)事務(wù)讀取。可防止臟讀,但幻影讀和不可重復(fù)讀仍可能會(huì)發(fā)生。
ISOLATION_REPEATABLE_READ:對(duì)相同字段的多次讀取的結(jié)果是一致的,除非數(shù)據(jù)被當(dāng)前事務(wù)本身改變??煞乐古K讀和不可重復(fù)讀,但幻讀仍可能發(fā)生。
ISOLATION_SERIALIZABLE:完全服從ACID的隔離級(jí)別,確保不發(fā)生臟讀、不可重復(fù)讀和幻影讀。
“怎么理解事務(wù)隔離級(jí)別、MVCC、spring事物傳播屬性”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。