sql查詢用nolock

你們在寫查詢時,爲了性能,每每會在表後面加一個nolock,或者是with(nolock),其目的就是查詢是不鎖定表,從而達到提升查詢速度的目的。程序員

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

1:髒讀,一個用戶對一個資源作了修改,此時另一個用戶正好讀取了這條被修改的記錄,而後,第一個用戶放棄修改,數據回到修改以前,這兩個不一樣的結果就是髒讀。數據庫

2:不可重複讀,一個用戶的一個操做是一個事務,這個事務分兩次讀取同一條記錄,若是第一次讀取後,有另外用戶修改了這個數據,而後第二次讀取的數據正好是其它用戶修改的數據,這樣形成兩次讀取的記錄不一樣,若是事務中鎖定這條記錄就能夠避免。安全

3:幻讀,指用戶讀取一批記錄的狀況,用戶兩次查詢同一條件的一批記錄,第一次查詢後,有其它用戶對這批數據作了修改,方法多是修改,刪除,新增,第二次查詢時,會發現第一次查詢的記錄條目有的不在第二次查詢結果中,或者是第二次查詢的條目不在第一次查詢的內容中。服務器

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

1> 鎖,每一個事務對所依賴的資源會請求不一樣類型的鎖,它能夠阻止其餘事務以某種可能會致使事務請求鎖出錯的方式修改資源。當事務再也不依賴鎖定的資源時,鎖將被釋放。性能

鎖的類型:1:表類型:鎖定整個表;2:行類型:鎖定某個行;3:文件類型:鎖定某個數據庫文件;4:數據庫類型:鎖定整個數據庫;5:頁類型:鎖定8K爲單位的數據庫頁。spa

鎖的分類還有一種分法,就是按用戶和數據庫對象來分:版本控制

1). 從數據庫系統的角度來看:分爲獨佔鎖(即排它鎖),共享鎖和更新鎖code

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,這種作法並不科學,起碼特別費時間,不如行版本控制來的直接有效。並且會存在不可預期的技術問題。應該有選擇性的挑選最適合的表來放棄共享鎖的使用。

最後說下nolockwith(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) 這樣就能夠

------以上是轉的

 

聽公司的dba說建議全部查詢都加上 with (nolock)

---------------

相關文章
相關標籤/搜索