事务的隔离性理解
事務(wù)處理之父Jim Gray對事務(wù)隔離性的定義:
Isolation: Concurrently executing transactions see the stored information as if they were running serially (one after another).
?
?
事務(wù)的隔離級別從低到高有:Read Uncommitted:最低的隔離級別,什么都不需要做,一個事務(wù)可以讀到另一個事務(wù)未提交的結(jié)果。所有的并發(fā)事務(wù)問題都會發(fā)生。
Read Committed:只有在事務(wù)提交后,其更新結(jié)果才會被其他事務(wù)看見。可以解決臟讀問題。
Repeated Read:在一個事務(wù)中,對于同一份數(shù)據(jù)的讀取結(jié)果總是相同的,無論是否有其他事務(wù)對這份數(shù)據(jù)進(jìn)行操作,以及這個事務(wù)是否提交。可以解決臟讀、不可重復(fù)讀。
Serialization:事務(wù)串行化執(zhí)行,隔離級別最高,犧牲了系統(tǒng)的并發(fā)性。可以解決并發(fā)事務(wù)的所有問題。
通常,在工程實(shí)踐中,為了性能的考慮會對隔離性進(jìn)行折中。 其中只有serialization實(shí)現(xiàn)隔離性所有要求,在真正實(shí)現(xiàn)事務(wù)的隔離性。 但考慮到實(shí)踐,為了性能,數(shù)據(jù)庫廠商做出了這方面的妥協(xié),讓使用者可以選擇隔離的級別。 不同的隔離級別可以解決不同階段的問題,是層層遞進(jìn),逐漸增強(qiáng)的關(guān)系。 隔離性為了解決的問題主要有三個(將事務(wù)的隔離級別和問題聯(lián)系在一起理解):
? ? ? ? 1、 臟讀(Drity Read):事務(wù)A修改了一個數(shù)據(jù),但未提交,事務(wù)B讀到了事務(wù)A未提交的更新結(jié)果,如果事務(wù)A提交失敗,事務(wù)B讀到的就是臟數(shù)據(jù)。
Read Committed可以解決臟讀問題,但仍存在以下兩種問題。
? ? ? ? ?2、不可重復(fù)讀(Non-repeatable read) :?在同一個事務(wù)中,對于同一份數(shù)據(jù)讀取到的結(jié)果不一致。比如,事務(wù)B在事務(wù)A提交前讀到的結(jié)果,和提交后讀到的結(jié)果可能不同。不可重復(fù)讀出現(xiàn)的原因就是事務(wù)并發(fā)修改記錄,要避免這種情況,最簡單的方法就是對要修改的記錄加鎖,這導(dǎo)致鎖競爭加劇,影響性能。(另一種方法是通過MVCC可以在無鎖的情況下,避免不可重復(fù)讀。待了解。。)
Repeated Read可以解決不可重復(fù)讀問題和臟讀問題,但仍無法解決下面的問題。
? ? ? ? ?3、幻讀(Phantom Read) :?在同一個事務(wù)中,同一個查詢多次返回的結(jié)果不一致。事務(wù)A新增了一條記錄,事務(wù)B在事務(wù)A提交前后各執(zhí)行了一次查詢操作,發(fā)現(xiàn)后一次比前一次多了一條記錄。幻讀僅指由于并發(fā)事務(wù)增加記錄導(dǎo)致的問題,這個不能像不可重復(fù)讀通過記錄加鎖解決,因?yàn)閷τ谛略龅挠涗浉緹o法加鎖。需要將事務(wù)串行化,才能避免幻讀。
Serialization解決了以上所有問題,但是性能效率較低。通常來說,事務(wù)隔離級別越低,所需持有鎖的時間也就越短,并發(fā)性能也就越好。
擴(kuò)展閱讀:
MySQL數(shù)據(jù)庫的InnoDB存儲引擎是支持事務(wù)的引擎,其默認(rèn)事務(wù)隔離級別為REPEATABLE READ(簡稱RR)。ANSI SQL標(biāo)準(zhǔn)下RR事務(wù)隔離級別是Degree 2.9999的隔離性,但是與ANSI SQL標(biāo)準(zhǔn)不同的是,InnoDB存儲引擎在RR的事務(wù)隔離級別下就解決了幻讀問題,從而實(shí)現(xiàn)Degree 3的隔離性要求,從而達(dá)到了真正隔離性的要求。對比其他數(shù)據(jù)庫,要達(dá)到真正的事務(wù)隔離性要求,必須將事務(wù)隔離級別設(shè)置為SERIALIZABLE。換句話說,MySQL InnoDB的默認(rèn)事務(wù)隔離級別可以理解為其他數(shù)據(jù)庫的SERIABLIZABLE級別。
然而,從嚴(yán)格意義上來說,InnoDB的RR事務(wù)隔離級別的實(shí)現(xiàn)與傳統(tǒng)的SERIALIAZABLE事務(wù)隔離級別還是有些不一樣,這導(dǎo)致在某些特定場景下會給用戶有錯愕抑或不能接受的感覺,比如唯一索引列在一個事務(wù)中允許重復(fù)值存在。不過這并不會破壞事務(wù)的一致性,只要理解InnoDB存儲引擎的鎖與MVCC的實(shí)現(xiàn),其實(shí)有些怪異的現(xiàn)象都好理解。
SNAPSHOT事務(wù)隔離級別
經(jīng)典的SERIALIAZABLE事務(wù)隔離級別采用嚴(yán)格的兩階段鎖(strict two-phrase lock,簡稱:STPL)實(shí)現(xiàn),這也是Jim Gray在書中提及的方法。但是由于讀寫都需要上鎖,這樣導(dǎo)致在大部分情況下事務(wù)的性能都不如類似RC(READ COMMITTED)這樣的事務(wù)隔離級別。
為了解決性能問題,最近越來越多的數(shù)據(jù)庫開始支持SNAPSHOT事務(wù)隔離級別(簡稱SI),如Oracle、PostgreSQL、Microsoft SQL Server數(shù)據(jù)庫等。SI事務(wù)隔離級別貌似解決了Dirty Read、Unrepeatable Read和Phantom Read問題。可惜的是,其依然不符合真正隔離性的要求,其存在write skew的異常問題。2008年的SIGMOD大會上,有人提出了Serializable Snapshot Isolation(SSI),從而解決了之前SI事務(wù)隔離級別存在的問題。PostgreSQL9.1版本在此論文基礎(chǔ)上實(shí)現(xiàn)了SSI事務(wù)隔離級別并做了相應(yīng)的優(yōu)化。此外,在2012年的VLDB大會上PostgreSQL發(fā)布了相應(yīng)的論文,有興趣的讀者可以繼續(xù)研究。
基于快照的事務(wù)隔離級別(不論SI還是SSI)性能較之經(jīng)典的SERIALIZABLE事務(wù)隔離級別提升非常多,但其存在兩個問題不容忽視。一是其會導(dǎo)致“錯誤”的回滾,因?yàn)槠洳呗跃褪潜WC正確,雖然有時可能會誤殺一些沒有問題的事務(wù)。二是對于大事務(wù)的支持需要額外的內(nèi)存保證,如果修改的數(shù)據(jù)量特別大,那么這可能會導(dǎo)致內(nèi)存溢出的問題發(fā)生。但不論怎么說,SSI可能都是未來的一個默認(rèn)事務(wù)隔離級別發(fā)展的方向。期待MySQL數(shù)據(jù)庫也能盡快支持。
參考:https://www.zhihu.com/question/31346392/answer/59815366、http://xm-king.iteye.com/blog/770721、http://www.tuicool.com/articles/ua6NJvb、https://www.zhihu.com/question/31346392/answer/51924208
轉(zhuǎn)載于:https://www.cnblogs.com/ws-astrologer/p/6681089.html
總結(jié)
- 上一篇: python - 函数
- 下一篇: sql server cvs 导入