SQL Server Insert操作中的鎖

2022-02-16 20:43:29 字數 2003 閱讀 3120

這篇博文簡單介紹一下在sql server中一條insert語句中用到的鎖。

首先我們建立一張表table_1,它有兩列id(bigint)和value(varchar),其中id建立了主鍵。

view code

然後插入兩條資料。

insert into dbo.table_2

(id, value)

values

(1, '1'),

(2, '2');

我們知道,在transaction中共享鎖在查詢語句結束就釋放了,而排它鎖則在transaction提交才釋放。我們可以利用它來執行乙個insert,不提交transaction,然後去檢視鎖的狀態。注意,本文中查詢視窗配置的transaction隔離級別是預設值read committed。

首先執行以下sql:

begin tran t1

insert into dbo.table_2

(id, value)

values

(3, '3');

然後檢視鎖:

select 

resource_type,

request_mode,

resource_description,

request_session_id,

request_status,

resource_associated_entity_id,

db_name(resource_database_id)as resource_database

from

sys.dm_tran_locks

where

resource_type <> 'database'

order by

request_session_id;

執行結果如下:

此時,我們在另外乙個命令視窗中執行以下查詢語句不會產生阻塞:

select *

from dbo.table_2

where id=1;

但另一條卻會產生阻塞:

select *

from dbo.table_2

where id=3;

來看看第一條sql產生的鎖。由於共享鎖會在查詢結束立即釋放,因此我們加乙個holdlock,讓它在事務結束再釋放:

begin tran t2

select *

from dbo.table_2 with(holdlock)

where id=1;

這是執行完以上語句鎖的情況:

第二條sql會產生阻塞,因此可以直接查詢然後看鎖的情況:

我們發現第9行的resource_description和第3行是相同的,這也說明了主鍵的鎖只是鎖住了某乙個值而已。

這條sql也會被insert阻塞:

select

value

from

dbo.table_2

where

value='1'

而且檢視當前的鎖可以發現,key被鎖的值正是insert語句的key值。這裡有兩個疑問:1. 為什麼沒用到主鍵列,卻產生了主鍵鎖。2.為什麼insert的資料還未commit,這裡卻會產生這一行主鍵的鎖。

答:1. 我們檢視查詢計畫,可以看到這條語句是用了聚集索引掃瞄,至於為什麼不是表掃瞄,請看這裡。 2. 由於事務隔離級別預設是read committed,所以這裡會對已插入但未提交的資料主鍵加乙個共享鎖。

出處:

SQL Server Insert操作中的鎖

這篇博文簡單介紹一下在sql server中一條insert語句中用到的鎖。首先我們建立一張表table 1,它有兩列id bigint 和value varchar 其中id建立了主鍵。create table dbo table 2 id bigint not null value nchar ...

SQL Server Insert操作中的鎖

這篇博文簡單介紹一下在sql server中一條insert語句中用到的鎖。首先我們建立一張表table 1,它有兩列id bigint 和value varchar 其中id建立了主鍵。view code 然後插入兩條資料。insert into dbo.table 2 id,value valu...

sqlserver insert 後的主鍵獲取方式

sql server 中,可以使用 scope identity identity ident current 來取得最後插入記錄的值值,它們的區別在於 scope identity 返回插入到同一作用域中的 identity 列內的最後乙個 identity 值。乙個作用域就是乙個模組 儲存過程 ...