脏读、幻读和不可重复读 + 事务隔离级别
- 丟失更新:兩個(gè)事務(wù)同時(shí)更新一行數(shù)據(jù),最后一個(gè)事務(wù)的更新會(huì)覆蓋掉第一個(gè)事務(wù)的更新,從而導(dǎo)致第一個(gè)事務(wù)更新的數(shù)據(jù)丟失,這是由于沒有加鎖造成的;
?
1.?臟讀?:臟讀就是指當(dāng)一個(gè)事務(wù)正在訪問數(shù)據(jù),并且對數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時(shí),另外一個(gè)事務(wù)也訪問這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。
?e.g.
??????? 1.Mary的原工資為1000, 財(cái)務(wù)人員將Mary的工資改為了8000(但未提交事務(wù))
????????2.Mary讀取自己的工資 ,發(fā)現(xiàn)自己的工資變?yōu)榱?000,歡天喜地!
??????? 3.而財(cái)務(wù)發(fā)現(xiàn)操作有誤,回滾了事務(wù),Mary的工資又變?yōu)榱?000
????????? 像這樣,Mary記取的工資數(shù)8000是一個(gè)臟數(shù)據(jù)。
?
2.?不可重復(fù)讀?:是指在一個(gè)事務(wù)內(nèi),多次讀同一數(shù)據(jù)。在這個(gè)事務(wù)還沒有結(jié)束時(shí),另外一個(gè)事務(wù)也訪問該同一數(shù)據(jù)。那么,在第一個(gè)事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個(gè)事務(wù)的修改,那么第一個(gè)事務(wù)兩次讀到的的數(shù)據(jù)可能是不一樣的。這樣在一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的,因此稱為是不可重復(fù)讀。
??? e.g.
??? 1.在事務(wù)1中,Mary 讀取了自己的工資為1000,操作并沒有完成
??? 2.在事務(wù)2中,這時(shí)財(cái)務(wù)人員修改了Mary的工資為2000,并提交了事務(wù).
??? 3.在事務(wù)1中,Mary 再次讀取自己的工資時(shí),工資變?yōu)榱?000
?解決辦法:如果只有在修改事務(wù)完全提交之后才可以讀取數(shù)據(jù),則可以避免該問題。
?
3.?幻讀?: 是指當(dāng)事務(wù)不是獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象,例如第一個(gè)事務(wù)對一個(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ā)生了幻覺一樣。
?? e.g.?
?? 目前工資為1000的員工有10人。
?? 1.事務(wù)1,讀取所有工資為1000的員工。
?? 2.這時(shí)事務(wù)2向employee表插入了一條員工記錄,工資也為1000
?? 3.事務(wù)1再次讀取所有工資為1000的員工 共讀取到了11條記錄,?
?
?解決辦法:如果在操作事務(wù)完成數(shù)據(jù)處理之前,任何其他事務(wù)都不可以添加新數(shù)據(jù),則可避免該問題
?
不可重復(fù)讀的重點(diǎn)是修改?:
?同樣的條件, 你讀取過的數(shù)據(jù),再次讀取出來發(fā)現(xiàn)值不一樣了
幻讀的重點(diǎn)在于新增或者刪除
?同樣的條件, 第 1 次和第 2 次讀出來的記錄數(shù)不一樣
?
參考:http://cupoy.iteye.com/blog/251796
http://blog.csdn.net/d8111/archive/2008/06/29/2595635.aspx
?http://www.iteye.com/topic/332577
?
?
?2、在一個(gè)程序中,依據(jù)事務(wù)的隔離級別將會(huì)有三種情況發(fā)生。
◆臟讀:一個(gè)事務(wù)會(huì)讀進(jìn)還沒有被另一個(gè)事務(wù)提交的數(shù)據(jù),所以你會(huì)看到一些最后被另一個(gè)事務(wù)回滾掉的數(shù)據(jù)。
◆不可重復(fù)讀:一個(gè)事務(wù)讀進(jìn)一條記錄,另一個(gè)事務(wù)更改了這條記錄并提交完畢,這時(shí)候第一個(gè)事務(wù)再次讀這條記錄時(shí),它已經(jīng)改變了。
◆ 幻影讀:一個(gè)事務(wù)用Where子句來檢索一個(gè)表的數(shù)據(jù),另一個(gè)事務(wù)插入一條新的記錄,并且符合Where條件,這樣,第一個(gè)事務(wù)用同一個(gè)where條件來檢索數(shù)據(jù)后,就會(huì)多出一條記錄。
?
3、數(shù)據(jù)庫提供了四種事務(wù)隔離級別, 不同的隔離級別采用不同的鎖類開來實(shí)現(xiàn).?
在四種隔離級別中, Serializable的級別最高, Read Uncommited級別最低.?
大多數(shù)數(shù)據(jù)庫的默認(rèn)隔離級別為: Read Commited,如Sql Server , Oracle.?
少數(shù)數(shù)據(jù)庫默認(rèn)的隔離級別為Repeatable Read, 如MySQL InnoDB存儲引擎
??
SQL SERVER鎖的機(jī)制?
?? SQL server的所有活動(dòng)都會(huì)產(chǎn)生鎖。鎖定的單元越小,就越能越能提高并發(fā)處理能力,但是管理鎖的開銷越大。如何找到平衡點(diǎn),使并發(fā)性和性能都可接受是SQL Server的難點(diǎn)。
SQL Server有如下幾種瑣:
?? SQL server的所有活動(dòng)都會(huì)產(chǎn)生鎖。鎖定的單元越小,就越能越能提高并發(fā)處理能力,但是管理鎖的開銷越大。如何找到平衡點(diǎn),使并發(fā)性和性能都可接受是SQL Server的難點(diǎn)。
SQL Server有如下幾種瑣:
1、 共享鎖
用于只讀操作(SELECT),鎖定共享的資源。共享鎖不會(huì)阻止其他用戶讀,但是阻止其他的用戶寫和修改。
2、 更新鎖
更新鎖是一種意圖鎖,當(dāng)一個(gè)事務(wù)已經(jīng)請求共享瑣后并試圖請求一個(gè)獨(dú)占鎖的時(shí)候發(fā)生更新瑣。例如當(dāng)兩個(gè)事務(wù)在幾行數(shù)據(jù)行上都使用了共享鎖,并同時(shí)試圖獲取獨(dú)占鎖以執(zhí)行更新操作時(shí),就發(fā)生了死鎖:都在等待對方釋放共享鎖而實(shí)現(xiàn)獨(dú)占鎖。更新鎖的目的是只讓一個(gè)事務(wù)獲得更新鎖,防止這種情況的發(fā)生。
3、 獨(dú)占鎖
一次只能有一個(gè)獨(dú)占鎖用在一個(gè)資源上,并且阻止其他所有的鎖包括共享縮。寫是獨(dú)占鎖,可以有效的防止’臟讀’。
4、 意圖縮
在使用共享鎖和獨(dú)占鎖之前,使用意圖鎖。從表的層次上查看意圖鎖,以判斷事務(wù)能否獲得共享鎖和獨(dú)占鎖,提高了系統(tǒng)的性能,不需從頁或者行上檢查。
5、 計(jì)劃鎖
Sch-M,Sch-S。對數(shù)據(jù)庫結(jié)構(gòu)改變時(shí)用Sch-M,對查詢進(jìn)行編譯時(shí)用Sch-S。這兩種鎖不會(huì)阻塞任何事務(wù)鎖,包括獨(dú)占鎖。
讀是共享鎖,寫是排他鎖,先讀后更新的操作是更新鎖,更新鎖成功并且改變了數(shù)據(jù)時(shí)更新鎖升級到排他鎖
?
l???? DEFAULT 使用數(shù)據(jù)庫設(shè)置的隔離級別 ( 默認(rèn) ) ,由 DBA 默認(rèn)的設(shè)置來決定隔離級別 .?
l???? READ_UNCOMMITTED 會(huì)出現(xiàn)臟讀、不可重復(fù)讀、幻讀 (?隔離級別最低,并發(fā)性能高?)?
l???? READ_COMMITTED? 會(huì)出現(xiàn)不可重復(fù)讀、幻讀問題(鎖定正在讀取的行)?
l???? REPEATABLE_READ 會(huì)出幻讀(鎖定所讀取的所有行)?
l???? SERIALIZABLE 保證所有的情況不會(huì)發(fā)生(鎖表)
?
ReadCommitted:?
假設(shè)A事務(wù)對正在讀取數(shù)據(jù)Data放置了共享鎖,那么Data不能被其它事務(wù)改寫,所以當(dāng)B事務(wù)對Data進(jìn)行讀取時(shí)總和A讀取的Data數(shù)據(jù)是一致的,所以避免了臟讀。由于在A沒有提交之前可以對Data進(jìn)行改寫,那么B讀取到的某個(gè)值可能會(huì)在其讀取后被A更改從而導(dǎo)致了該值不能被重復(fù)取得;或者當(dāng)B再次用相同的where字句時(shí)得到了和前一次不一樣數(shù)據(jù)的結(jié)果集,也就是幻像數(shù)據(jù)。
ReadUncommitted:
假設(shè)A事務(wù)即不發(fā)布共享鎖,也不接受獨(dú)占鎖,那么并發(fā)的B或者其它事務(wù)可以改寫A事務(wù)讀取的數(shù)據(jù),那么并發(fā)的C事務(wù)讀取到的數(shù)據(jù)的狀態(tài)和A的或者B的數(shù)據(jù)都可能不一致,那么。臟讀、不可重復(fù)讀、幻象數(shù)據(jù)都可能存在。
RepeatableRead:
(注意MSDN原文中的第一句話:在查詢中使用的所有數(shù)據(jù)上放置鎖,所以不存在臟讀的情況)。
假設(shè)A事務(wù)對讀取的所有數(shù)據(jù)Data放置了鎖,以阻止其它事務(wù)對Data的更改,在A沒有提交之前,新的并發(fā)事務(wù)讀取到的數(shù)據(jù)如果存在于Data中,那么該數(shù)據(jù)的狀態(tài)和A事務(wù)中的數(shù)據(jù)是一致的,從而避免了不可重復(fù)的讀取。但在A事務(wù)沒有結(jié)束之前,B事務(wù)可以插入新記錄到Data所在的表中,那么其它事務(wù)再次用相同的where字句查詢時(shí),得到的結(jié)果數(shù)可能上一次的不一致,也就是幻像數(shù)據(jù)。
Serializable:
?在數(shù)據(jù)表上放置了排他鎖,以防止在事務(wù)完成之前由其他用戶更新行或向數(shù)據(jù)集中插入行,這是最嚴(yán)格的鎖。它防止了臟讀、不可重復(fù)讀取和幻象數(shù)據(jù)。
from:?http://uule.iteye.com/blog/1109647
總結(jié)
以上是生活随笔為你收集整理的脏读、幻读和不可重复读 + 事务隔离级别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里巴巴代码规范-note
- 下一篇: 谈谈对Canal( 增量数据订阅与消费