《轉》SQL中with nolock 詳解

2022-03-08 22:55:12 字數 2414 閱讀 9617

大家在寫查詢時,為了效能,往往會在表後面加乙個nolock,或者是with(nolock),其目的就是查詢是不鎖定表,從而達到提高查詢速度的目的。

什麼是併發訪問:同一時間有多個使用者訪問同一資源,併發使用者中如果有使用者對資源做了修改,此時就會對其它使用者產生某些不利的影響,例如:

1:髒讀,乙個使用者對乙個資源做了修改,此時另外乙個使用者正好讀取了這條被修改的記錄,然後,第乙個使用者放棄修改,資料回到修改之前,這兩個不同的結果就是髒讀。

2:不可重複讀,乙個使用者的乙個操作是乙個事務,這個事務分兩次讀取同一條記錄,如果第一次讀取後,有另外使用者修改了這個資料,然後第二次讀取的資料正好是其它使用者修改的資料,這樣造成兩次讀取的記錄不同,如果事務中鎖定這條記錄就可以避免。

3:幻讀,指使用者讀取一批記錄的情況,使用者兩次查詢同一條件的一批記錄,第一次查詢後,有其它使用者對這批資料做了修改,方法可能是修改,刪除,新增,第二次查詢時,會發現第一次查詢的記錄條目有的不在第二次查詢結果中,或者是第二次查詢的條目不在第一次查詢的內容中。

為什麼會在查詢的表後面加nolock標識?為了避免併發訪問產生的不利影響,sql server有兩種併發訪問的控制機制:鎖、行版本控制,表後面加nolock是解決併發訪問的方案之一。

1> 鎖,每個事務對所依賴的資源會請求不同型別的鎖,它可以阻止其他事務以某種可能會導致事務請求鎖出錯的方式修改資源。當事務不再依賴鎖定的資源時,鎖將被釋放。

鎖的型別:1:表型別:鎖定整個表;2:行型別:鎖定某個行;3:檔案型別:鎖定某個資料庫檔案;4:資料庫型別:鎖定整個資料庫;5:頁型別:鎖定8k為單位的資料庫頁。

鎖的分類還有一種分法,就是按使用者和資料庫物件來分:

1). 從資料庫系統的角度來看:分為獨佔鎖(即排它鎖),共享鎖和更新鎖

1:共享 (s) :用於不更改或不更新資料的操作(唯讀操作),一般常見的例如select語句。

2:更新 (u) :用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。

3:排它 (x) :用於資料修改操作,例如 insert、update 或 delete。確保不會同時同一資源進行多重更新。

2). 從程式設計師的角度看:分為樂觀鎖和悲觀鎖。

1:樂觀鎖:完全依靠資料庫來管理鎖的工作。

2:悲觀鎖:程式設計師自己管理資料或物件上的鎖處理。

一般程式設計師一看到什麼鎖之類,覺的特別複雜,對專業的dba當然是入門級知識了。可喜的是程式設計師不用去設定,控制這些鎖,sqlserver通過設定事務的隔離級別自動管理鎖的設定和控制。鎖管理器通過查詢分析器分析待執行的sql語句,來判斷語句將會訪問哪些資源,進行什麼操作,然後結合設定的隔離級別自動分配管理需要用到的鎖。

2>:行版本控制:當啟用了基於行版本控制的隔離級別時,資料庫引擎 將維護修改的每一行的版本。應用程式可以指定事務使用行版本檢視事務或查詢開始時存在的資料,而不是使用鎖保護所有讀取。通過使用行版本控制,讀取操作阻止其他事務的可能性將大大降低。也就是相當於針對所有的表在查詢時都會加上nolock,同樣會產生髒讀的現象,但差別在於在乙個統一管理的地方。說到了基於行版本控制的隔離級別,這裡有必要說下隔離級別的概念。

隔離級別的用處:控制鎖的應用,即什麼場景應用什麼樣的鎖機制。

最終目的:解決併發處理帶來的種種問題。

隔離級別的分類:

1:未提交讀,隔離事務的最低級別,只能保證不讀取物理上損壞的資料;

2:已提交讀,資料庫引擎的缺省級;

3:可重複讀;

4:可序列化;隔離事務的最高端別,事務之間完全隔離。

小結:nolock 語句執行時不發出共享鎖,允許髒讀 ,等於 read uncommitted事務隔離級別 。nolock確實在查詢時能提高速度,但它並不是沒有缺點的,起碼它會引起髒讀。

nolock的使用場景(個人觀點):

1:資料量特別大的表,犧牲資料安全性來提公升效能是可以考慮的;

2:允許出現髒讀現象的業務邏輯,反之一些資料完整性要求比較嚴格的場景就不合適了,像金融方面等。

3:資料不經常修改的表,這樣會省於鎖定表的時間來大大加快查詢速度。

綜上所述,如果在專案中的每個查詢的表後面都加nolock,這種做法並不科學,起碼特別費時間,不如行版本控制來的直接有效。而且會存在不可預期的技術問題。應該有選擇性的挑選最適合的表來放棄共享鎖的使用。

最後說下nolock和with(nolock)的幾個小區別:

1:sql05中的同義詞,只支援with(nolock);

2:with(nolock)的寫法非常容易再指定索引。

跨伺服器查詢語句時 不能用with (nolock) 只能用nolock

同乙個伺服器查詢時 則with (nolock)和nolock都可以用

比如sql code

select * from [ip].a.dbo.table1 with

(nolock) 這樣會提示用錯誤

select * from a.dbo.table1 with

(nolock) 這樣就可以

SQL中with nolock 作用說明

例如 select count userid from employee with nolock join working group with nolock onemployee.userid working group.userid 因為sql server會執行對應的鎖定一致性檢查。欲改善整體...

SQL允許髒讀WITH NOLOCK

使用wiht nolock 有利也有弊,所以在決定使用之前,你一定需要了解清楚with nolock 的功能和缺陷,看其是否適合你的業務需求,不要覺得它能提公升效能,稀里糊塗的就使用它。事務未提交回滾 begin tran update dbo.student set ca 6666 where n...

SQL 全形轉半形

if exists select from dbo.sysobjects where id object id n dbo f convert and xtype in n fn n if n tf drop function dbo f convert go 全形 半形轉換 轉換說明 全形字符從的...