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