2014-02-19 6 views
5

Ein Kollege schrieb eine Abfrage, die die Hinweise "mit (NOLOCK, NOWAIT)" verwendet.Warum NOLOCK und NOWAIT zusammen verwenden?

z.B.

select first_name, last_name, age 
from people with (nolock,nowait) 

Annahmen:

NOLOCK sagt „keine Sorge über alle Sperren auf jeder Ebene, lesen Sie einfach die Daten nun“

NOWAIT sagt „warten Sie nicht, nur Fehler, wenn der Tisch
Warum beide zugleich:

Frage „gesperrt? Sicher wird NOWAIT nie realisiert werden, denn NOLOCK bedeutet, dass es sowieso nicht auf Schlösser warten würde ...?

+0

Warum nicht Sie versuchen, es mit einigen Testdaten und sehen was h Benennungen ?! –

+1

Haben Sie schon getan, es kehrte sofort - dh. NOLOCK hat gewonnen - meine Frage stellt sich "warum sie zusammen nutzen? Gibt es einen Umstand, in dem NOLOCK nicht gewinnen würde?" – Richard

+0

Ich denke du hast recht, dass das 'nowait' überflüssig ist, aber hoffentlich wird jemand mit einiger Autorität antworten! –

Antwort

5

Es ist redundant (oder zumindest unwirksam). In einem Abfragefenster ausführen:

create table T (ID int not null) 
begin transaction 
alter table T add ID2 int not null 

Lassen Sie dieses Fenster geöffnet ist, öffnen Sie eine andere Abfrage-Fenster und führen:

select * from T WITH (NOLOCK,NOWAIT) 

Trotz der NOWAIT Hinweis, und obwohl es als Rückkehr eine Nachricht dokumentiert wird, sobald Wenn eine Sperre gefunden wird, bleibt diese zweite Abfrage hängen und wartet auf die Schema-Sperre.

Lesen Sie die Dokumentation auf Table Hints:

NOWAIT:

Weist den Datenbankmodul eine Nachricht zurück, sobald eine Sperre für die Tabelle

Hinweis

begegnet ist, dass Dies ist eine Sperre, jeder Sperre.

NOLOCK (eigentlich READUNCOMMITTED):

READUNCOMMITTED und NOLOCK Hinweise gelten nur für Datensperren. Alle Abfragen, einschließlich derjenigen mit READUNCOMMITTED- und NOLOCK-Hints, erwerben Sch-S-Sperren (Schema Stability) während der Kompilierung und Ausführung. Aus diesem Grund werden Abfragen blockiert, wenn eine gleichzeitige Transaktion eine Sch-M-Sperre (Schema Modification) für die Tabelle enthält.

So NOLOCK braucht für einige Schleusen zu warten.

3

NOLOCK ist die gleiche wie READUNCOMMITTED, für die MSDN states:

... exklusive Sperren von anderen Transaktionen gesetzt nicht blockieren die aktuelle Transaktion die gesperrten Daten zu lesen.

auf diesem Satz Basierend, würde ich sagen, dass Sie richtig sind und dass NOLOCK effektiv Ausgabe bedeutet, dass alle Datensperren irrelevant sind, so NOWAIT ist überflüssig, da die Abfrage nicht blockiert werden kann.

Allerdings geht der Artikel weiter:

READUNCOMMITTED und NOLOCK Hinweise gelten nur für Datensperren

Sie können auch Schemaänderung Sperren bekommen, und NOLOCK diese nicht ignorieren können. Wenn Sie eine Abfrage mit NOLOCK abgesetzt haben, während ein Schemaobjekt aktualisiert wurde, ist es möglich, dass Ihre Abfrage durch eine Sperre vom Typ Sch-M blockiert wurde.

Es wäre interessant zu sehen, ob in diesem unwahrscheinlichen Fall die NOWAIT tatsächlich respektiert wird. Aber für Ihre Zwecke würde ich sagen, dass es wahrscheinlich überflüssig ist.

+1

Nur den Test gemacht. 'NOWAIT' blockiert immer noch das Warten auf die Schema-Sperre, also scheint es doch überflüssig zu sein. –

+0

@Damien_The_Unbeliever - Es wird nicht einmal in der Lage sein, die Abfrage zu kompilieren und mit der Ausführung zu beginnen, so dass der Hinweis nie wirklich in die Abfrage eingeht. 'SET LOCK_TIMEOUT 0; GO wählen * aus T WITH (NOLOCK)' wäre die einzige Möglichkeit, dies zu tun AFAIK. –

1

Es macht keinen Sinn, sie zusammen zu verwenden. NOLOCK überschreibt das Verhalten von NOWAIT. Hier ist eine Demonstration der NOWAIT Funktionalität. Kommentiere im NOLOCK und sieh zu, wie die Aufzeichnungen trotz der Exklusivsperre zurückkehren.

Erstellen Sie die Tabelle. Führen Sie das 1. SSMS-Fenster aus, ohne die Transaktion zu übernehmen. Führen Sie das zweite Fenster aus, erhalten Sie einen Fehler, weil Sie nicht warten müssen. Kommentieren Sie die erste Abfrage und führen Sie die zweite Abfrage mit NOLOCK und NOWAIT aus. Ergebnisse bekommen. Rollback Ihre Transaktion, wenn Sie fertig sind.

DDL

USE [tempbackup] 
GO 

/****** Object: Table [TEST_TABLE] Script Date: 02/19/2014 09:14:00 ******/ 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

SET ANSI_PADDING ON 
GO 

CREATE TABLE [TEST_TABLE](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [varchar](50) NULL, 
CONSTRAINT [PK_TEST_TABLE] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

SET ANSI_PADDING OFF 
GO 

INSERT INTO tempbackup.dbo.TEST_TABLE(Name) VALUES ('MATT') 

GO 

SSMS FENSTER 1

BEGIN TRANSACTION 

UPDATE tempbackup.dbo.TEST_TABLE WITH(XLOCK) SET Name = 'RICHARD' WHERE ID = 1 

--ROLLBACK TRANSACTION 

SSMS FENSTER 2

SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOWAIT) 
--SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOLOCK,NOWAIT) 
Verwandte Themen