2009-09-21 89 views
114

我在做網站和應用程序的業務是而不是任務關鍵 - >例如。銀行軟件,太空飛行,重症監護應用等等。你明白了。NOLOCK(Sql Server提示)不好的做法?

那麼,有了這種大規模的免責聲明,在某些Sql語句中使用NOLOCK提示是不是很糟糕?幾年前,Sql管理員建議我使用NOLOCK,如果我對「髒讀」感到滿意,這會讓我的系統性能提高一點,因爲每次讀取都不會鎖定表/行/不管。

我被告知,如果我遇到死鎖,這是一個很好的解決方案。所以,我開始關注這個想法幾年,直到一位Sql guru幫我一些隨機代碼,並注意到我的sql代碼中的所有NOLOCKS。我被禮貌地責罵,他試圖向我解釋(爲什麼它不是一件好事),我總是迷失方向。我覺得他的解釋的實質是「這是一個更嚴重問題的創可貼解決方案,尤其是如果你遇到了僵局。因此,解決問題的根源'。

我最近做了一些關於谷歌搜索,並跨越this post來了。

那麼,可以一些sql db guru sensei的請賜教嗎?

+0

我不明白Sam,如果它是一個繁重的閱讀網站,請說使用快照隔離。但是,那麼你說這麼做,那很糟糕?或者只是使用NOLOCK? – 2009-09-21 11:47:14

回答

63

使用NOLOCK提示,SELECT語句的事務隔離級別爲READ UNCOMMITTED。這意味着查詢可能會看到髒和不一致的數據。

這不是一個好主意。即使您的任務關鍵型基於Web的應用程序的這種髒讀取行爲正常,NOLOCK掃描也會導致601錯誤,這將由於缺少鎖定保護而導致數據移動而終止查詢。

我建議閱讀When Snapshot Isolation Helps and When It Hurts - MSDN的建議在大多數情況下使用讀提交快照而不是快照。

+0

雷克斯,請隨時添加關於快照隔離的說明。 – 2009-09-21 06:01:09

+2

是的,山姆說快照隔離,你建議讀取提交快照。我很困惑:P(我還沒有深入研究文章,也!) – 2009-09-21 11:49:11

+2

它偶爾有用,但通常不用於生產。我經常使用它來抽出一個數據樣本來進行測試或生成報告,我主要關心粗略的數量級,在這種情況下,髒讀無關緊要。 – TimothyAWiseman 2012-05-14 22:50:15

19

如果你不在乎髒讀(即在主要閱讀的情況),那麼NOLOCK是罰款。

,要知道,大多數的鎖定問題是由於沒有「正確的」索引查詢的工作量(假設硬件是完成這一任務)。

而古魯的解釋是正確的。對於更嚴重的問題,它通常是一種創可貼的解決方案。

編輯:我絕對不是說應該使用NOLOCK。我想我應該明確地表明這一點。 (我只會使用它,在極端的情況下,我已經分析過它是可以的)。作爲一個例子,前一段時間,我在一些已經使用NOLOCK的TSQL上工作,試圖緩解鎖定問題。我把它們都刪除了,實現了正確的索引,所有的死鎖都消失了。

+3

嗯..我還是不明白。所以這很好,但它也是一個糟糕的形式..是你在說什麼? – 2009-09-21 05:41:15

+0

假設你從不關心臟讀,那麼它不會受到傷害。但它通常是治療症狀,而不是原因... – 2009-09-21 05:49:19

+2

嗯,我不認爲它的公平rexem只是downvoted,我認爲你沒有解決任何錯誤,只是浮起來,當你使用nolock。在您的網站上偶爾會出現一個空白的錯誤頁面並不好,它的確很糟糕。我不喜歡這樣的斷言:「如果你不在乎髒讀取它的罰款」......即使你不在乎髒讀 – 2009-09-21 05:55:46

95

在使用堆棧溢出之前,我的原則是針對NOLOCK,您可能會執行SELECTNOLOCK並獲取可能過期或不一致的數據的結果。需要考慮的一個因素是可以同時插入/更新多少個記錄,同時另一個進程可以從同一個表中選擇數據。如果這種情況發生很多,那麼除非使用數據庫模式(如READ COMMITED SNAPSHOT),否則很有可能出現死鎖。

因爲我目睹瞭如何改進SELECT性能以及消除大容量加載的SQL Server上的死鎖後,我改變了對NOLOCK的使用的看法。有時候,您可能並不在乎您的數據不完全是100%提交,即使它們可能已過期,也需要快速返回結果。

問自己一個問題使用NOLOCK的思考時:

難道我的查詢包含有大量的INSERT/UPDATE命令的表,做我不在乎,如果從查詢返回的數據可能會丟失這些變化在特定時刻?

如果答案是否定的,則使用NOLOCK來提高性能。


我剛剛在Stack Overflow的代碼庫中執行了 NOLOCK關鍵字的快速搜索,發現了138個實例,所以我們在很多地方使用它。

+7

IMO,這有點簡單。通過使用覆蓋索引可以消除死鎖,從集羣索引中減去壓力。 – 2009-09-21 06:27:49

+5

我不想減少良好指數覆蓋的重要性。有些時候,使用NOLOCK的查詢可以在大量插入/更新的表上通過索引實現的增益之外添加額外的性能。即使以不準確或缺失的數據爲代價,Stack Overflow上的查詢速度也是至關重要的。 – 2009-09-21 06:54:49

+0

謝謝讓Geoff爲答案。我需要消化它,但我一直在尋找一些關於如何從早期處理它們的僵局問題的答案。我從來沒有讀過他們研究或解決問題的任何「結果」,因爲它。 – 2009-09-21 11:50:58

7

沒有一個答案是錯誤的,但也許有點混淆。

  • 當查詢單值/排它總是不好的做法,使用NOLOCK - 你可能永遠都不想顯示不正確的信息,或者甚至採取不正確的數據採取任何行動。
  • 當顯示粗略統計信息時,NOLOCK可能非常有用。以SO爲例:使用鎖來讀取問題的數量或標籤的確切問題數量將是無稽之談。沒有人在意你現在是否錯誤地陳述了3360個標有「sql-server」的問題,並且由於事務回滾,在一秒鐘之後有3359個問題。
+0

我不同意你的第一點。如果您正在查詢單個值/行,並且您正在爲該行指定唯一的ID,並且您知道沒有其他進程將訪問它,那麼使用nolock是完全可以接受的,並且可以減少併發應用程序中的阻塞。 – tuseau 2011-05-16 12:16:21

+0

不,它不是。該行可能因其他原因而改變,例如插入另一行來拆分頁面。正確的索引,讀取提交的快照和快照隔離幾乎總是更好的想法。 – 2012-04-26 16:48:38

+0

@tuseau如果您「知道」沒有其他進程訪問該行,那麼鎖定行爲不會阻止任何事情,因此您的(實際上)任何成本都沒有, – 2016-04-18 04:55:59

13

疑問,這是一個「大師」誰喝了在高流量的經驗......

網站通常是由時間「髒」的人觀看完全加載頁面。考慮從數據庫加載的表單,然後保存編輯的數據?這是愚蠢的人們繼續關於骯髒的閱讀是這樣的一個不行。

也就是說,如果您的選擇有多個圖層,那麼您可能會構建一個危險的冗餘。如果您在處理金錢或狀態方面的問題,那麼您不僅需要事務性數據讀取/寫入,而且還需要一個適當的併發解決方案(大多數「大師」並不打擾)。另一方面,如果您有一個先進的產品搜索網站(即可能不會緩存並且有點密集的東西),並且您曾經構建過一個網站,並且擁有多個併發用戶(有多少「專家」沒有),唾棄其後的所有其他流程是很荒謬的。

知道是什麼意思,並在適當的時候使用它。現在你的數據庫幾乎總是你的主要瓶頸,而且使用NOLOCK可以爲你節省成千上萬的基礎設施。

編輯:這不僅僅是它幫助的死鎖,它還是你要讓其他人等待多久才能完成,反之亦然。

Using NOLOCK Hint in EF4?

2

的專業開發我會說這要看情況。但我絕對遵循GATS和OMG Ponies的建議。知道你在做什麼,知道什麼時候它有助於當它傷害和

閱讀hints and other poor ideas

什麼能讓你瞭解SQL服務器更深。我通常遵循SQL Hints是EVIL的規則,但不幸的是,當我厭倦了強迫SQL Server執行操作時,我偶爾會使用它們......但這些情況很少見。

盧克

2

當應用程序支持想回答使用SSMS(即不通過報告照顧)從生產服務器的廣告,典當查詢我要求他們使用NOLOCK。這樣,「主要」業務不受影響。

2

我同意一些關於NOLOCK暗示的評論,特別是那些說「在適當時使用它」的評論。 如果應用程序寫得不好並且使用併發性不當的方式 - 那可能導致鎖升級。由於其性質,高度交易的桌子也一直處於鎖定狀態。具有良好的指數覆蓋範圍將無助於檢索數據,但將隔離級別設置爲READ UNCOMMITTED。 另外我相信,在許多情況下,如果變化的性質是可預測的,則使用NOLOCK提示是安全的。例如 - 在製造時,當旅行者的工作經歷了大量插入測量的不同過程時,您可以安全地使用NOLOCK提示對完成的工作執行查詢,並且這樣可以避免與其他會將PROMOTED或EXCLUSIVE鎖放在桌面上的會話相沖突/頁。在這種情況下訪問的數據是靜態的,但它可能駐留在一個非常事務性的表中,每個分鐘有數以億計的記錄和數千次更新/插入。 乾杯

1

的更好的解決方案,在可能的情況是:

  • 複製數據(使用日誌的複製)到報告數據庫中。
  • 使用SAN快照和安裝DB
  • 使用具有更好的基本事務隔離級別

快照事務隔離級別的形成是因爲MS正在失去銷售到Oracle數據庫的版本一致。 Oracle使用撤銷/重做日誌來避免這個問題。 Postgres使用MVCC。未來,MS的Heckaton將使用MVCC,但距離生產準備還有幾年的時間。

+0

上面有一個錯字。我的意思是說「更好的基本事務隔離機制」。 – pwy 2014-02-07 22:37:27

+1

SNAPSHOT事務隔離級別是MS的發明。基本上它將數據放入TEMPDB的臨時表中。該數據庫在盒子上的所有數據庫之間共享。所以,如果可能的話,您會希望將SSD用於TEMPDB。這可能比其他選項少。 – pwy 2014-02-07 23:08:29

2

我相信使用nolock幾乎是不對的。

如果你正在讀單行,那麼正確的指數意味着,各行的操作快速完成你不需要NOLOCK。

如果你正在讀許多行比臨時顯示其他什麼,而在乎能重複的結果,或通過辯護產生的號碼,然後NOLOCK是不恰當的。

NOLOCK是

錯誤這下是可能的,「如果這個答案包含重複行,行被刪除,或從來沒有插入開始,因爲回滾與行我不在乎」的替代品標籤NOLOCK:

  • 匹配的行根本不返回。
  • 單行返回多次(包括同一主鍵的多個實例)
  • 返回不匹配的行。

在noLock選擇運行時可導致頁面拆分的任何操作都可能導致發生這些情況。幾乎任何操作(即使是刪除)都可能導致頁面拆分。

因此:如果你「知道」,而你正在運行該行不會被改變,不NOLOCK使用,作爲索引將允許高效的檢索。

如果您懷疑查詢運行時,該行可以改變,你在意的準確性,不要使用NOLOCK。

如果你正在考慮,因爲死鎖NOLOCK,檢查意外表掃描查詢計劃結構,跟蹤死鎖,看看他們爲什麼會發生。寫入周圍的NOLOCK可能意味着先前死鎖的查詢可能會寫出錯誤的答案。

0

NOLOCK經常利用爲神奇方式來加快數據庫中讀取,但我會盡量避免使用它whever可能。

結果集可以包含尚未提交的行,這往往是後回滾。

錯誤或結果集可能爲空,可能缺少行或多次顯示相同的行。

這是因爲其他交易在您讀取數據的同時正在移動數據。

READ COMMITTED添加其中的數據被多個用戶同時改變相同的小區的單個列中損壞一個額外的問題。

-2

在你遇到已經寫入系統和添加索引的表,然後急劇減慢一個14gig數據表的數據加載現實生活中,你有時不得不使用NOLOCK在您的報告和月proessing的結束,使得將使用的聚合函數(總和,計數等)不會執行行,頁面,表鎖定並降低整體性能。 在新系統中容易說,不要使用WITH NOLOCK並使用索引 - 但是添加索引會嚴重降級數據加載,並且當我被告知時,更改代碼庫以刪除索引,然後批量加載然後重新創建索引 - 如果你正在開發一個新系統,這一切都很好。但是,當你有一個系統已經到位。