溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MSSQL數(shù)據(jù)庫中事務(wù)隔離級別和鎖機制介紹

發(fā)布時間:2021-09-13 21:54:40 來源:億速云 閱讀:88 作者:chen 欄目:數(shù)據(jù)庫

這篇文章主要講解了“MSSQL數(shù)據(jù)庫中事務(wù)隔離級別和鎖機制介紹”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“MSSQL數(shù)據(jù)庫中事務(wù)隔離級別和鎖機制介紹”吧!

鎖機制NOLOCK和READPAST的區(qū)別。

1. 開啟一個事務(wù)執(zhí)行插入數(shù)據(jù)的操作。

BEGIN TRAN tINSERT INTO CustomerSELECT 'a','a'

2. 執(zhí)行一條查詢語句。

SELECT * FROM Customer WITH (NOLOCK)

結(jié)果中顯示”a”和”a”。當(dāng)1中事務(wù)回滾后,那么a將成為臟數(shù)據(jù)。(注:1中的事務(wù)未提交) 。NOLOCK表明沒有對數(shù)據(jù)表添加共享鎖以阻止其它事務(wù)對數(shù)據(jù)表數(shù)據(jù)的修改。

SELECT * FROM Customer

這條語句將一直死鎖,直到排他鎖解除或者鎖超時為止。(注:設(shè)置鎖超時SET LOCK_TIMEOUT 1800)

SELECT * FROM Customer WITH (READPAST)

這條語句將顯示a未提交前的狀態(tài),但不鎖定整個表。這個提示指明數(shù)據(jù)庫引擎返回結(jié)果時忽略加鎖的行或數(shù)據(jù)頁。

3. 執(zhí)行一條插入語句。

BEGIN TRAN tINSERT INTO CustomerSELECT 'b','b'COMMIT TRAN t

這個時候,即使步驟1的事務(wù)回滾,那么a這條數(shù)據(jù)將丟失,而b繼續(xù)插入數(shù)據(jù)庫中。

NOLOCK

1. 執(zhí)行如下語句。

BEGIN TRAN tttSELECT * FROM Customer WITH (NOLOCK)WAITFOR delay '00:00:20'COMMIT TRAN ttt

注:NOLOCK不加任何鎖,可以增刪查改而不鎖定。

INSERT INTO Customer SELECT 'a','b' –不鎖定DELETE Customer where ID=1 –不鎖定SELECT * FROM Customer –不鎖定UPDATE Customer SET Title='aa' WHERE ID=1 –不鎖定

ROWLOCK

1. 執(zhí)行一條帶行鎖的查詢語句。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ -- (必須)BEGIN TRAN tttSELECT * FROM Customer WITH (ROWLOCK) WHERE ID=17WAITFOR delay '00:00:20'COMMIT TRAN ttt

注:在刪除和更新正在查詢的數(shù)據(jù)時,會鎖定數(shù)據(jù)。對其他未查詢的行和增加,查詢數(shù)據(jù)無影響。

INSERT INTO Customer SELECT 'a','b' –不等待DELETE Customer where ID=17 –等待DELETE Customer where ID<>17 –不等待SELECT * FROM Customer –不等待UPDATE Customer SET Title='aa' WHERE ID=17–等待UPDATE Customer SET Title='aa' WHERE ID<>17–不等待

HOLDLOCK,TABLOCK和TABLOCKX

1. 執(zhí)行HOLDLOCK

BEGIN TRAN tttSELECT * FROM Customer WITH (HOLDLOCK)WAITFOR delay '00:00:10'COMMIT TRAN ttt

注:其他事務(wù)可以讀取表,但不能更新刪除

update Customer set Title='aa' —要等待10秒中。

SELECT * FROM Customer —不需要等待

2. 執(zhí)行TABLOCKX

BEGIN TRAN tttSELECT * FROM Customer WITH (TABLOCKX)WAITFOR delay '00:00:10'COMMIT TRAN ttt

注:其他事務(wù)不能讀取表,更新和刪除

update Customer set Title='aa' —要等待10秒中。

SELECT * FROM Customer —要等待10秒中。

3. 執(zhí)行TABLOCK

BEGIN TRAN tttSELECT * FROM Customer WITH (TABLOCK)WAITFOR delay '00:00:10'COMMIT TRAN ttt

注:其他事務(wù)可以讀取表,但不能更新刪除

update Customer set Title='aa' —要等待10秒中。

SELECT * FROM Customer —不需要等待

UDPLOCK

1. 在A連接中執(zhí)行。

BEGIN TRAN tttSELECT * FROM Customer WITH (UPDLOCK)WAITFOR delay '00:00:10'COMMIT TRAN ttt

2. 在其他連接中執(zhí)行。

update Customer set Title='aa' where ID=1—要等10秒

SELECT * FROM Customer –不用等

insert into Customer select 'a','b'–不用等

注:對于UDPLOCK鎖,只對更新數(shù)據(jù)鎖定。

注:使用這些選項將使系統(tǒng)忽略原先在SET語句設(shè)定的事務(wù)隔離級別(SET Transaction Isolation Level)。

事務(wù)隔離級別

臟讀:READ UNCOMMITTED

臟讀就是指當(dāng)一個事務(wù)正在訪問數(shù)據(jù),并且對數(shù)據(jù)進行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時,另外一個事務(wù)也訪問這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。因為這個數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個事務(wù)讀到的這個數(shù)據(jù)是臟數(shù)據(jù),依據(jù)臟數(shù)據(jù)所做的操作可能是不正確的。

1. 在A連接中執(zhí)行。

BEGIN TRAN tINSERT INTO CustomerSELECT '123','123'WAITFOR delay '00:00:20'COMMIT TRAN t

2. 在B連接中執(zhí)行。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDSELECT * FROM Customer

這個時候,未提交的數(shù)據(jù)會'123'會顯示出來,當(dāng)A事務(wù)回滾時就導(dǎo)致了臟數(shù)據(jù)。相當(dāng)于(NOLOCK)

提交讀:READ COMMITTED

1. 在A連接中執(zhí)行。

BEGIN TRAN tINSERT INTO CustomerSELECT '123','123'WAITFOR delay '00:00:20'COMMIT TRAN t

2. 在B連接中執(zhí)行。

SET TRANSACTION ISOLATION LEVEL READ COMMITTEDSELECT * FROM Customer

這個時候,未提交的數(shù)據(jù)會'123'不會顯示出來,當(dāng)A事務(wù)提交以后B中才能讀取到數(shù)據(jù)。避免了臟讀。

不可重復(fù)讀:REPEATABLE READ

不可重復(fù)讀是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù)。在這個事務(wù)還沒有結(jié)束時,另外一個事務(wù)也訪問該同一數(shù)據(jù)。那么,在第一個事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個事務(wù)的修改,那么第一個事務(wù)兩次讀到的數(shù)據(jù)可能是不一樣的。這樣就發(fā)生了在一個事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的,因此稱為是不可重復(fù)讀。

例如:

1. 在A連接中執(zhí)行如下語句。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READBEGIN TRAN tttSELECT * FROM Customer WHERE ID=17WAITFOR delay '00:00:30'SELECT * FROM Customer WHERE ID=17COMMIT TRAN ttt

2. 在B連接中執(zhí)行如下語句,而且要在第一個事物的三十秒等待內(nèi)。

UPDATE Customer SET Title='d' WHERE ID=17

這個時候,此連接將鎖住不能執(zhí)行,一直等到A連接結(jié)束為止。而且A連接中兩次讀取到的數(shù)據(jù)相同,不受B連接干擾。

注,對于Read Committed和Read UnCommitted情況下,B連接不會鎖住,等到A連接執(zhí)行完以后,兩條查詢語句結(jié)果不同,即第二條查詢的Title變成了d。

序列化讀:SERIALIZABLE

1. 在A連接中執(zhí)行。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLEBEGIN TRAN tUPDATE Customer SET Title='111'WAITFOR delay '00:00:20'COMMIT TRAN t

2. 在B連接中執(zhí)行,并且要在A執(zhí)行后的20秒內(nèi)。

BEGIN TRAN ttINSERT INTO CustomerSELECT '2','2'COMMIT TRAN tt

在A連接的事務(wù)提交之前,B連接無法插入數(shù)據(jù)到表中,這就避免了幻覺讀。

注:幻覺讀是指當(dāng)事務(wù)不是獨立執(zhí)行時發(fā)生的一種現(xiàn)象,例如 第一個事務(wù)對一個表中的數(shù)據(jù)進行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時,第二個事務(wù)也修改這個表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,以后就會發(fā)生操作第一個事務(wù)的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好像發(fā)生了幻覺一樣。

共享鎖

共享鎖(S 鎖)允許并發(fā)事務(wù)在封閉式并發(fā)控制(請參閱并發(fā)控制的類型)下讀取 (SELECT) 資源。資源上存在共享鎖(S 鎖)時,任何其他事務(wù)都不能修改數(shù)據(jù)。讀取操作一完成,就立即釋放資源上的共享鎖(S 鎖),除非將事務(wù)隔離級別設(shè)置為可重復(fù)讀或更高級別,或者在事務(wù)持續(xù)時間內(nèi)用鎖定提示保留共享鎖(S 鎖)。

更新鎖

更新鎖(U 鎖)可以防止常見的死鎖。在可重復(fù)讀或可序列化事務(wù)中,此事務(wù)讀取數(shù)據(jù) [獲取資源(頁或行)的共享鎖(S 鎖)],然后修改數(shù)據(jù) [此操作要求鎖轉(zhuǎn)換為排他鎖(X 鎖)]。如果兩個事務(wù)獲得了資源上的共享模式鎖,然后試圖同時更新數(shù)據(jù),則一個事務(wù)嘗試將鎖轉(zhuǎn)換為排他鎖(X 鎖)。共享模式到排他鎖的轉(zhuǎn)換必須等待一段時間,因為一個事務(wù)的排他鎖與其他事務(wù)的共享模式鎖不兼容;發(fā)生鎖等待。第二個事務(wù)試圖獲取排他鎖(X 鎖)以進行更新。由于兩個事務(wù)都要轉(zhuǎn)換為排他鎖(X 鎖),并且每個事務(wù)都等待另一個事務(wù)釋放共享模式鎖,因此發(fā)生死鎖。

若要避免這種潛在的死鎖問題,請使用更新鎖(U 鎖)。一次只有一個事務(wù)可以獲得資源的更新鎖(U 鎖)。如果事務(wù)修改資源,則更新鎖(U 鎖)轉(zhuǎn)換為排他鎖(X 鎖)。

排他鎖

排他鎖(X 鎖)可以防止并發(fā)事務(wù)對資源進行訪問。使用排他鎖(X 鎖)時,任何其他事務(wù)都無法修改數(shù)據(jù);僅在使用 NOLOCK 提示或未提交讀隔離級別時才會進行讀取操作。

數(shù)據(jù)修改語句(如 INSERT、UPDATE 和 DELETE)合并了修改和讀取操作。語句在執(zhí)行所需的修改操作之前首先執(zhí)行讀取操作以獲取數(shù)據(jù)。因此,數(shù)據(jù)修改語句通常請求共享鎖和排他鎖。例如,UPDATE 語句可能根據(jù)與一個表的聯(lián)接修改另一個表中的行。在此情況下,除了請求更新行上的排他鎖之外,UPDATE 語句還將請求在聯(lián)接表中讀取的行上的共享鎖。

感謝各位的閱讀,以上就是“MSSQL數(shù)據(jù)庫中事務(wù)隔離級別和鎖機制介紹”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對MSSQL數(shù)據(jù)庫中事務(wù)隔離級別和鎖機制介紹這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI