臟讀、幻讀、不可重復(fù)讀與失去更新案例
發(fā)表時(shí)間:2023-09-02 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]2017年6月5日,天氣——雨。 前兩天整理之前的學(xué)習(xí)筆記時(shí),發(fā)現(xiàn)對(duì)事務(wù)并發(fā)產(chǎn)生的問題——臟讀、幻讀、不可重復(fù)讀和丟失更新這些概念有點(diǎn)模糊,于是又重新溫習(xí)了一遍,現(xiàn)在把自己的一些理解歸納整理如下,方便大家學(xué)習(xí)。 鎖就是防止其他事務(wù)訪問指定資源的手段。鎖是實(shí)現(xiàn)并發(fā)控制的主要方法...
2017年6月5日,天氣——雨。
前兩天整理之前的學(xué)習(xí)筆記時(shí),發(fā)現(xiàn)對(duì)事務(wù)并發(fā)產(chǎn)生的問題——臟讀、幻讀、不可重復(fù)讀和丟失更新這些概念有點(diǎn)模糊,于是又重新溫習(xí)了一遍,現(xiàn)在把自己的一些理解歸納整理如下,方便大家學(xué)習(xí)。
鎖就是防止其他事務(wù)訪問指定資源的手段。鎖是實(shí)現(xiàn)并發(fā)控制的主要方法,是多個(gè)用戶能夠同時(shí)操縱同一個(gè)數(shù)據(jù)庫(kù)中的數(shù)據(jù)而不發(fā)生數(shù)據(jù)不一致現(xiàn)象的重要保障。 一般來說,鎖可以防止臟讀、不可重復(fù)讀和幻讀。
1.臟讀(Dirty Read)——一個(gè)事務(wù)讀取到了另外一個(gè)事務(wù)沒有提交的數(shù)據(jù)。
詳細(xì)解釋:當(dāng)一個(gè)事務(wù)正在訪問數(shù)據(jù)并且對(duì)數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫(kù)中,這時(shí)另外一個(gè)事務(wù)也訪問這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。因?yàn)檫@個(gè)數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個(gè)事務(wù)讀到的這個(gè)數(shù)據(jù)是臟數(shù)據(jù),依據(jù)臟數(shù)據(jù)所做的操作可能是不正確的。
事務(wù)T1:更新一條數(shù)據(jù)
-->事務(wù)T2:讀取事務(wù)T1更新的記錄
事務(wù)T1:調(diào)用commit進(jìn)行提交
此時(shí)事務(wù)T2讀取到的數(shù)據(jù)是保存在數(shù)據(jù)庫(kù)內(nèi)存中的數(shù)據(jù),稱為臟數(shù)據(jù),這個(gè)過程稱為臟讀。
臟讀發(fā)生在一個(gè)事務(wù)A讀取了被另一個(gè)事務(wù)B修改,但是還未提交的數(shù)據(jù)。假如B回退,則事務(wù)A讀取的是無效的數(shù)據(jù)。這跟不可重復(fù)讀類似,但是第二個(gè)事務(wù)不需要執(zhí)行提交。
解決臟讀問題:修改時(shí)加排他鎖,直到事務(wù)提交后才釋放,讀取時(shí)加共享鎖,讀取完釋放事務(wù)1讀取數(shù)據(jù)時(shí)加上共享鎖后(這樣在事務(wù)1讀取數(shù)據(jù)的過程中,其他事務(wù)就不會(huì)修改該數(shù)據(jù)),不允許任何事務(wù)操作該數(shù)據(jù),只能讀取,之后1如果有更新操作,那么會(huì)轉(zhuǎn)換為排他鎖,其他事務(wù)更無權(quán)參與進(jìn)來讀寫,這樣就防止了臟讀問題。但是當(dāng)事務(wù)1讀取數(shù)據(jù)過程中,有可能其他事務(wù)也讀取了該數(shù)據(jù),讀取完畢后共享鎖釋放,此時(shí)事務(wù)1修改數(shù)據(jù),修改完畢提交事務(wù),其他事務(wù)再次讀取數(shù)據(jù)時(shí)候發(fā)現(xiàn)數(shù)據(jù)不一致,就會(huì)出現(xiàn)不可重復(fù)讀問題,所以這樣不能夠避免不可重復(fù)讀問題。
2.幻讀(Phantom)——同一事務(wù)中,用同樣的操作讀取兩次,得到的記錄數(shù)不相同。
詳細(xì)解釋:幻讀是指當(dāng)事務(wù)不是獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象,例如第一個(gè)事務(wù)對(duì)一個(gè)表中的數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時(shí),第二個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,以后就會(huì)發(fā)生操作第一個(gè)事務(wù)的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺一樣。
事務(wù)T1:查詢表中所有記錄
-->事務(wù)T2:插入一條記錄
-->事務(wù)T2:調(diào)用commit進(jìn)行提交
事務(wù)T1:再次查詢表中所有記錄
此時(shí)事務(wù)T1兩次查詢到的記錄是不一樣的,稱為幻讀。
注意:幻讀重點(diǎn)在新增或刪除。
幻讀發(fā)生在當(dāng)兩個(gè)完全相同的查詢執(zhí)行時(shí),第二次查詢所返回的結(jié)果集跟第一個(gè)查詢不相同。
發(fā)生的情況:沒有范圍鎖。
如何避免:實(shí)行序列化隔離模式,在任何一個(gè)低級(jí)別的隔離中都可能會(huì)發(fā)生。
解決幻讀問題:采用的是范圍鎖RangeS RangeS_S模式,鎖定檢索范圍為只讀,這樣就避免了幻讀問題。
3.不可重復(fù)讀(Nonrepeatable Read)——在同一事務(wù)中,兩次讀取同一數(shù)據(jù),得到內(nèi)容不同。
事務(wù)T1:查詢一條記錄
-->事務(wù)T2:更新事務(wù)T1查詢的記錄
-->事務(wù)T2:調(diào)用commit進(jìn)行提交
事務(wù)T1:再次查詢上次的記錄
此時(shí)事務(wù)T1對(duì)同一數(shù)據(jù)查詢了兩次,可得到的內(nèi)容不同,稱為不可重復(fù)讀。
注意:不可重復(fù)讀重點(diǎn)在修改。
在基于鎖的并行控制方法中,如果在執(zhí)行select時(shí)不添加讀鎖,就會(huì)發(fā)生不可重復(fù)讀問題。
在多版本并行控制機(jī)制中,當(dāng)一個(gè)遇到提交沖突的事務(wù)需要回退但卻被釋放時(shí),會(huì)發(fā)生不可重復(fù)讀問題。
有兩個(gè)策略可以防止這個(gè)問題的發(fā)生:
(1) 推遲事務(wù)2的執(zhí)行,直至事務(wù)1提交或者回退。這種策略在使用鎖時(shí)應(yīng)用。
(2) 而在多版本并行控制中,事務(wù)2可以被先提交,而事務(wù)1繼續(xù)執(zhí)行在舊版本的數(shù)據(jù)上。當(dāng)事務(wù)1終于嘗試提交時(shí),數(shù)據(jù)庫(kù)會(huì)檢驗(yàn)它的結(jié)果是否和事務(wù)1、事務(wù)2順序執(zhí)行時(shí)一樣。如果是,則事務(wù)1提交成功;如果不是,事務(wù)1會(huì)被回退。
解決不可重復(fù)讀問題:讀取數(shù)據(jù)時(shí)加共享鎖,寫數(shù)據(jù)時(shí)加排他鎖,都是事務(wù)提交才釋放鎖。讀取時(shí)候不允許其他事物修改該數(shù)據(jù),不管數(shù)據(jù)在事務(wù)過程中讀取多少次,數(shù)據(jù)都是一致的,避免了不可重復(fù)讀問題。
4.丟失更新(Lost Update)
事務(wù)T1讀取了數(shù)據(jù),并執(zhí)行了一些操作,然后更新數(shù)據(jù)。事務(wù)T2也做相同的事,則T1和T2更新數(shù)據(jù)時(shí)可能會(huì)覆蓋對(duì)方的更新,從而引起錯(cuò)誤。
5.處理以上隔離級(jí)別的問題,采用如下方法:
事務(wù)隔離五種級(jí)別:
(1)TRANSACTION_NONE 不使用事務(wù)。
(2)TRANSACTION_READ_UNCOMMITTED 允許臟讀。
(3)TRANSACTION_READ_COMMITTED 防止臟讀,最常用的隔離級(jí)別,并且是大多數(shù)數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別。
(4)TRANSACTION_REPEATABLE_READ 可以防止臟讀和不可重復(fù)讀。
(5)TRANSACTION_SERIALIZABLE 可以防止臟讀,不可重復(fù)讀取和幻讀,(事務(wù)串行化)會(huì)降低數(shù)據(jù)庫(kù)的效率。
以上的五個(gè)事務(wù)隔離級(jí)別都是在Connection接口中定義的靜態(tài)常量,使用setTransactionIsolation(int level) 方法可以設(shè)置事務(wù)隔離級(jí)別。
如:con.setTransactionIsolation(Connection.REPEATABLE_READ)。
注意:事務(wù)的隔離級(jí)別受數(shù)據(jù)庫(kù)的限制,不同的數(shù)據(jù)庫(kù)支持的的隔離級(jí)別不一定相同。
以上就是臟讀、幻讀、不可重復(fù)讀和丟失更新實(shí)例的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
學(xué)習(xí)教程快速掌握從入門到精通的SQL知識(shí)。