預設情況下select會使用共享鎖, 在資料讀取完後會立即釋放; insert, update, delete會對更改的資料使用排它鎖並且一直保持到事務結束. 共享鎖可以與共享鎖,更新鎖共存. 排它鎖與任何鎖都不能共存.
例1: 新建一張表 create table table1 (id int), 加入一條記錄 insert into table1 values(1) 在查詢分析器中開兩個連線 連線1:
begintran
select
*from
table1
連線2:
update
table1
setid =1
先執行連線1, 再執行連線2, 都是立即完成. 然後連線1改為:
while
@@trancount
>
0rollback
tran
--如果有未提交的事務就回滾
begin
tran
update
table1
setid =1
連線2不變 先執行連線1, 再執行連線2, 會發現連線2被阻塞. 這時在連線1中單獨執行commit tran, 連線2會立即結束. 注:在測試過程中可以用select @@spid檢視當前連線的spid, 用sp_lock檢視鎖資訊. 如果要改變隱性鎖, 可以使用with關鍵字.
例2:
連線1:
while
@@trancount
>
0rollback
tran
begin
tran
select
*from
table1
with
(holdlock
)
連線2:
update
table1
setid =1
先執行連線1, 再執行連線2, 連線2會被阻塞. 因為holdlock改變了共享鎖的生存期, 讓共享鎖保持到事務結束, 而共享鎖與排它鎖是不能共存的.
連線1改為:
while
@@trancount
>
0rollback
tran
begin
tran
select
*from
table1
with
(tablockx)
先執行連線1, 再執行連線2, 連線2仍會被阻塞. 這裡指定select使用表級排它鎖, 該鎖會保持到事務結束, 所以這裡不用加holdlock.
例3:
連線1:
while
@@trancount
>
0rollback
tran
insert
into
table1
values(2
)begin
tran
update
table1
setid =3
where
id =
2
連線2:
select
*from
table1
先執行連線1, 再執行連線2, 連線2會被阻塞. 連線2:
select top 1 * from table1
再執行連線2, 連線2會立即結束. 為了使鎖定的成本減至最少,sql server 自動將資源鎖定在適合任務的級別. 這裡會使用行級鎖. update的過程應該先是查詢id=2的記錄, 查詢時使用共享鎖, 不滿足id=2的記錄共享鎖立即釋放, 滿足id=2的記錄把共享鎖公升級為排它鎖並保持到事務結束. 所以第一次執行連線2會因為無法獲取id=2的記錄的共享鎖而被阻塞, 而第二次執行不會被阻塞.
golang 併發鎖的陷阱
package main import sync strconv fmt type node struct var cache node func main cache 1 node wg sync.waitgroup for i 0 i 10000 i i wg.wait fmt.println ...
SQL server鎖的機制
sql server 的所有活動都會產生鎖。鎖定的單元越小,就越能越能提高併發處理能力,但是管理鎖的開銷越大。如何找到平衡點,使併發性和效能都可接受是 sql server 的難點。sql server 有如下幾種瑣 1 共享鎖用於唯讀操作 select 鎖定共享的資源。共享鎖不會阻止其他使用者讀,...
SQL Server 控制鎖公升級
背景知識 鎖公升級的路線圖 行 頁 區 extent 區 表分割槽 表 alter table 控制鎖的公升級行為 1 table sql server 2008中的預設行為,設為這個值時,在表級別啟用了鎖公升級,不管表是否分割槽。2 auto 如果以分割槽就在分割槽級別啟用鎖公升級,如果沒有分割槽...