關於Update語句的鎖
環境:MSSQL2005,在Read Committed級別
語句A:
begin tran
Update Table Set f1='xxx' where f2='ttt' --更新一行或多行
--commit; //注意為了看到效果這里把commit注釋了
語句A影響的行集合為B
該語句造成的影響
1.該語句會阻塞,查詢結果集合含有任意B集合中的行的select 語句
2.該語句會阻塞,對該表其它行(B集合以外)進行Update操作的語句
語句B:
Update Table Set f4='xxxx' where f3='xxx' ,注意 這里的f3列上無索引,否則不會阻塞。
問題分析:
當update 語句的where條件涉及列是非索引列時,MSSQL查詢引擎會執行全表掃描,在這個過程中會對每一行加上U鎖,如果該行是目標行,那么U鎖會升級成X鎖,然后進行更新操作,而非目標行的U鎖會在數據讀取完后馬上釋放
如下圖
如果你沒有執行commit語句,可以使用SP_Lock查看update查詢進程的鎖情況
這個時候當語句B執行時,B需要在每行上獲取一次U鎖,這個時候就會碰到上面未釋放的X鎖定行
當然如果語句B中的where 條件使用的是索引列,那么語句B只會在索引涉及的列上加U鎖,如果A,B更新查詢的影響行無交集那么A,B查詢互不影響。
圖)設置sql profiler的Lock項目