標籤:style blog http 使用 資料 2014 ar 資料庫
1、建立一個表,插入1010000資料:
create table test(id int identity(1,1) ,name varchar(600)) goinsert into testvalues(replicate('a',600));go 1010000create index idx_test_id on test(id)
2、新開一個會話(A),運行如下語句,由於沒有提交,所以會阻塞其他藥修改相同資料的會話:
begin tranupdate test set name = replicate('f',500)where id = 100000
3、再新開一個會話(B),運行如下語句,由於需要修改id為 100000的資料,所以被上一個會話A阻塞了。
需要特別注意的是,在語句中使用了查詢提示repeatableread,那麼select語句對記錄擷取的S鎖,只有在commit或rollback時,才會釋放。
begin transelect *from test with(repeatableread)where id >= 9000 and id <= 100000select sysdatetime()
4、再開一個會話(C),運行如下語句,由於需要修改id為100000的資料,所以被會話A阻塞了
begin tran update test set name = replicate('k',589)where id = 100000select sysdatetime()
5、在會話A中,通過commit來提交事務,這個時候,會話B會馬上返回結果,但會話C還是繼續被阻塞,這個時候C被B會話阻塞。
接下來,在會話B中執行commit,於是會話C立即返回。
從以上的現象大致能看出,資料庫鎖中的隊列機制,也就是當很多會話都需要訪問相同的資源時,會有一個隊列機制,一開始A對資源加上獨佔鎖,擷取到資源,但沒有提交,所以沒有釋放資源上的鎖。
會話B也需要訪問相同的資源,由於會話需要讀資料,所以需要加上共用鎖定,但由於共用鎖定和之前資源上的獨佔鎖,不相容,就導致了會話B被阻塞住了,那麼會話B就進入到一個等待隊列裡。
會話C也需要訪問相同的資源,由於需要修改資料,所以需要加上獨佔鎖,但於會話A已加上的獨佔鎖,不相容,於是會話C也被阻塞住了,那麼會話C也會進入到等待隊列中,排在會話B之後。
會話C被阻塞的原因:
從可以看出,會話C在把Page 1 :21339上的IU鎖改為IX鎖時,沒有grant,而是處於convert狀態,之所要修改,是因為需要修改id為100000的資料。
而之前已經在1 :21339上加了IU鎖,在RID 1:21339:1 上加了U鎖,要修改這個這個頁中的資料,必須要把IU鎖修改為IX鎖,如果成功,那麼繼續把U鎖修改為X鎖。
從上述分析中,可以看出SQL Server中的鎖採用是隊列的機制,即先進先出。