SQLSERVER Update 行鎖(rowlock)

 

在高併發的狀況下,關係型數據庫死鎖是很難避免的問題,研發能作的是,儘可能減小死鎖的可能性,那麼就要求研發對數據庫鎖的機制有至關的瞭解,從而針對問題,儘量的避免死鎖的發生。今天抽空,談一談關於update語句條件對鎖的影響。我看了網絡上的一篇文章,大體意思是sql

在進行update操做時,where條件是否使用主鍵或索引,對鎖的級別將會有影響,具體內容以下:數據庫

下面摘自網絡的一段問內容:服務器

ROWLOCK告訴 SQL  Server只使用行級鎖。ROWLOCK語法能夠使用在SELECT, UPDATE和DELETE語句中,不過 我習慣僅僅在UPDATE和DELETE語句中使用。若是在UPDATE語句中有指定的主鍵,那麼就老是會引起行級鎖的。可是當SQL  Server對幾個這種UPDATE進行批處理時,某些數據正好在同一個頁面(page),這種狀況在當前狀況下  是頗有可能發生的,這就象在一個folder中,建立一個新文件須要較長的時間,而同時你又要去更新該folder中的某些文件。當頁面鎖引起後,事情就開始變得糟糕了。而若是在UPDATE或者DELETE 時,沒有指定主鍵,數據庫固然認爲不少數據會收到影響,那樣 就會直接引起頁面鎖,事情一樣變得糟糕。
經過指定使用行級鎖,這種狀況能夠獲得避免。可是須要當心的是,若是你錯誤地使用在過多行上,數據庫並不會聰明到自動將行級鎖升級到頁面鎖,服務器也會由於行級鎖的開銷而消耗大量的內存和CPU,直至沒法響應。尤爲主要留意的是 企業管理器中"管理/當前活動"(Management /Current  Activity)這一項。該項會花較長的時間來載入鎖的信息。這些信息是十分有用的,當你使用行級鎖後,你若是在"鎖/處理" (Locks/Processes)下看到幾百個鎖,一點都不奇怪,而偏偏應該慶幸鎖超時和死鎖的問題減小了。   網絡

 

驗證併發

爲此,我建了一張表,進行update操做。高併發

首先,根據非主鍵字段MessageId,進行更新,打開一個事務,咱們稱爲sql1吧。code

begin tran 
  update [Messages] set RecordDate=GETDATE() where MessageId='7dd2de03-7693-4dd2-adbf-093e00b3cf7d';
  waitfor delay '00:00:05' 
  commit tran

然再打開一個會話,編寫一個根據主鍵更新的sql,咱們稱爲sql2吧blog

update [Messages] set RecordDate=GETDATE() where Id='1326';

這種狀況下,按照文中所說,在執行第一個sql後,再執行第二段sql,因爲事務中的update語句條件根據非主鍵更新的,全部致使pagelock,因而,咱們在事務提交前,執行第二段SQL,就會處於等待狀態。索引

而後咱們在作第二個驗證,把事務中的update where條件改爲主鍵,咱們稱爲sql3吧。事務

begin tran
  update [Messages] set RecordDate=GETDATE() where Id='1327'  
  waitfor delay '00:00:05' 
  commit tran

一樣等待5秒。

而後先執行sql3,啓動sql3後,立馬執行sql2,看看效果,

直接是一行受影響,這也就驗證了咱們這篇文章中的觀點:"若是在UPDATE語句中有指定的主鍵,那麼就老是會引起行級鎖的"。

相關文章
相關標籤/搜索