這篇博文簡單介紹一下在sql server中一條insert語句中用到的鎖。
首先我們建立一張表table_1,它有兩列id(bigint)和value(varchar),其中id建立了主鍵。
view code
然後插入兩條資料。
insert into dbo.table_2我們知道,在transaction中共享鎖在查詢語句結束就釋放了,而排它鎖則在transaction提交才釋放。我們可以利用它來執行乙個insert,不提交transaction,然後去檢視鎖的狀態。注意,本文中查詢視窗配置的transaction隔離級別是預設值read committed。(id, value)
values
(1, '1'),
(2, '2');
首先執行以下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 *來看看第一條sql產生的鎖。由於共享鎖會在查詢結束立即釋放,因此我們加乙個holdlock,讓它在事務結束再釋放:from dbo.table_2
where id=3;
begin tran t2這是執行完以上語句鎖的情況:select *
from dbo.table_2 with(holdlock)
where id=1;
第二條sql會產生阻塞,因此可以直接查詢然後看鎖的情況:
我們發現第9行的resource_description和第3行是相同的,這也說明了主鍵的鎖只是鎖住了某乙個值而已。
這條sql也會被insert阻塞:
select而且檢視當前的鎖可以發現,key被鎖的值正是insert語句的key值。這裡有兩個疑問:1. 為什麼沒用到主鍵列,卻產生了主鍵鎖。2.為什麼insert的資料還未commit,這裡卻會產生這一行主鍵的鎖。value
from
dbo.table_2
where
value='1'
答: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 值。乙個作用域就是乙個模組 儲存過程 ...