隔离级别
自從知道事務的隔離級別已經(jīng)很長時間了,一直處于半理解的狀態(tài),這幾天看了很多的博客,對隔離級別有了更深的了解,覺得很有必要把自己的理解寫下來。
1.首先我們要知道為什么事務要分隔離級別。
如果沒有隔離級別的話,數(shù)據(jù)庫操作過程中會出現(xiàn)一下狀況
更新丟失(Lost update)
兩個事務都同時更新一行數(shù)據(jù),但是第二個事務卻中途失敗退出,導致對數(shù)據(jù)的兩個修改都失效了。這是因為系統(tǒng)沒有執(zhí)行任何的鎖操作,因此并發(fā)事務并沒有被隔離開來。
臟讀(Dirty Reads)
一個事務開始讀取了某行數(shù)據(jù),但是另外一個事務已經(jīng)更新了此數(shù)據(jù)但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作都被回滾。
不可重復讀(Non-repeatable Reads)
一個事務對同一行數(shù)據(jù)重復讀取兩次,但是卻得到了不同的結果。它包括以下情況:
(1) 事務T1讀取某一數(shù)據(jù)后,事務T2對其做了修改,當事務T1再次讀該數(shù)據(jù)時得到與前一次不同的值。
(2) 幻讀(Phantom Reads):事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現(xiàn)的數(shù)據(jù)或者缺少了第一次查詢中出現(xiàn)的數(shù)據(jù)(這里并不要求兩次查詢的SQL語句相同)。這是因為在兩次查詢過程中有另外一個事務插入數(shù)據(jù)造成的。
可能有些人看到這些概念會有似是而非的感覺,為了能讓大家更好的理解這些概念,下面我們通過例子說明這幾種情況
Create Table Student
(
Name varchar(50),
Age int,
Address varchar(50)
)
Insert into Student values('小明',15,'北京')
Insert into Student values('小王',16,'天津')
a.更新丟失
有兩個事務T1 和T2
T1操作為
update student set Age = 16 where name ='小明'
T2操作為
update student set Address = '武漢' where name ='小明'
T1 與T2同是開始,也就是T1和T2這兩個事務開始的時候 小明信息為('小明',15,'北京')
T1成功,小明信息更改為 ('小明',16,'北京');
T2失敗,事務回滾到操作之前的狀態(tài) 小明信息變?yōu)?'小明',15,'北京')
T2的失敗造成T1的更新丟失,這就叫做更新丟失,避免更新丟失的方法就是加排他寫鎖,排他寫鎖就是當一個事務在編輯這條信息的時候,禁止其他事務進行寫操作。
2.臟讀
一個用戶對一個資源做了修改,此時另外一個用戶正好讀取了這條被修改的記錄,然后,第一個用戶放棄修改,數(shù)據(jù)回到修改之前,這兩個不同的結果就是臟讀。(即B用戶讀取了一個A用戶沒有提交事務的數(shù)據(jù)(rollback transaction),這樣讀出來的數(shù)據(jù)是屬于臟數(shù)據(jù))
下面是簡單的例子來實現(xiàn)臟讀:
首先T1為
begin tran
update Student set Age = 16 where Name = ‘小明’
waitfor delay '00:00:05' --延遲五秒
rollback tran --回滾事務
事務T2
select * from Student with(nolock) where Name = ‘小明’
-- 加 with(nolock)可以讀到未提交的數(shù)據(jù),能提高查詢性能,但它并不是沒有缺點的,作為一個負面影響,nolock查詢還可能帶來讀取“幻影”數(shù)據(jù)或讀取在一個數(shù)據(jù)庫讀取事務中可以獲得的但在另一個事務中可能被滾回的數(shù)據(jù)的風險。
先執(zhí)行T1,一兩秒之后執(zhí)行T2,五秒之后再次執(zhí)行T2,會發(fā)現(xiàn)中間有一個查詢結果小明年齡為16,后來因為事務回滾,造成查詢結果又變回為15,而年齡為16的這條數(shù)據(jù)就是臟數(shù)據(jù)。
3. 不可重復讀 :是指在一個事務內(nèi),多次讀同一數(shù)據(jù)。在這個事務還沒有結束時,另外一個事務也訪問該同一數(shù)據(jù)。那么,在第一個事務中的兩次讀數(shù)據(jù)之間,由于第二個事務的修改,那么第一個事務兩次讀到的的數(shù)據(jù)可能是不一樣的。這樣在一個事務內(nèi)兩次讀到的數(shù)據(jù)是不一樣的,因此稱為是不可重復讀。
事務1第一次讀小明的年齡為15
事務2更新小明年齡為16
事務1第二次讀小明年齡為16
事務1的兩次查詢不一樣
解決辦法:如果只有在修改事務完全提交之后才可以讀取數(shù)據(jù),則可以避免該問題
4. 幻讀 : 是指當事務不是獨立執(zhí)行時發(fā)生的一種現(xiàn)象,例如第一個事務對一個表中的數(shù)據(jù)進行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時,第二個事務也修改這個表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,以后就會發(fā)生操作第一個事務的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺一樣。
事務1第一次查詢學生信息為兩條數(shù)據(jù)
事務2向學生表中插入一條新的信息
事務1第二次查詢學生信息是發(fā)現(xiàn)多了一條 產(chǎn)生幻讀
解決辦法:如果在操作事務完成數(shù)據(jù)處理之前,任何其他事務都不可以添加新數(shù)據(jù),則可避免該問題
2. 隔離級別
●未授權讀取(讀未提交)(Read Uncommitted):允許臟讀取,但不允許更新丟失。如果一個事務已經(jīng)開始寫數(shù)據(jù),則另外一個數(shù)據(jù)則不允許同時進行寫操作,但允許其他事務讀此行數(shù)據(jù)。該隔離級別可以通過“排他寫鎖”實現(xiàn)。
●授權讀取(讀提交)(Read Committed):允許不可重復讀取,但不允許臟讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現(xiàn)。讀取數(shù)據(jù)的事務允許其他事務繼續(xù)訪問該行數(shù)據(jù),但是未提交的寫事務將會禁止其他事務訪問該行。
●可重復讀取(Repeatable Read):禁止不可重復讀取和臟讀取,但是有時可能出現(xiàn)幻影數(shù)據(jù)。這可以通過“共享讀鎖”和“排他寫鎖”實現(xiàn)。讀取數(shù)據(jù)的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。
●序列化(Serializable):提供嚴格的事務隔離。它要求事務序列化執(zhí)行,事務只能一個接著一個地執(zhí)行,但不能并發(fā)執(zhí)行。如果僅僅通過“行級鎖”是無法實現(xiàn)事務序列化的,必須通過其他機制保證新插入的數(shù)據(jù)不會被剛執(zhí)行查詢操作的事務訪問到。
隔離級別越高,越能保證數(shù)據(jù)的完整性和一致性,但是對并發(fā)性能的影響也越大。對于多數(shù)應用程序,可以優(yōu)先考慮把數(shù)據(jù)庫系統(tǒng)的隔離級別設為Read Committed,它能夠避免臟讀取,而且具有較好的并發(fā)性能。盡管它會導致不可重復讀、虛讀和第二類丟失更新這些并發(fā)問題,在可能出現(xiàn)這類問題的個別場合,可以由應用程序采用悲觀鎖或樂觀鎖來控制。
總結
- 上一篇: echarts的x轴数量固定_联轴器 多
- 下一篇: 完全理解icmp协议