Confuso su UPDLOCK, HOLDLOCK


89

Durante la ricerca sull'uso dei suggerimenti per la tabella , mi sono imbattuto in queste due domande:

Le risposte a entrambe le domande dicono che durante l'utilizzo (UPDLOCK, HOLDLOCK), altri processi non saranno in grado di leggere i dati su quella tabella, ma non l'ho visto. Per testare, ho creato una tabella e avviato due finestre SSMS. Dalla prima finestra, ho eseguito una transazione selezionata dalla tabella utilizzando vari suggerimenti di tabella. Mentre la transazione era in esecuzione, dalla seconda finestra ho eseguito varie istruzioni per vedere quale sarebbe stata bloccata.

La tabella dei test:

CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
 CONSTRAINT [PK_Test] 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]

Dalla finestra SSMS 1:

BEGIN TRANSACTION

SELECT * FROM dbo.Test WITH (UPDLOCK, HOLDLOCK)
WAITFOR DELAY '00:00:10'

COMMIT TRANSACTION

Dalla finestra SSMS 2 (eseguito uno dei seguenti):

SELECT * FROM dbo.Test
INSERT dbo.Test(Value) VALUES ('bar')
UPDATE dbo.Test SET Value = 'baz' WHERE Value = 'bar'
DELETE dbo.Test WHERE Value= 'baz'

Effetto di diversi suggerimenti di tabella sulle istruzioni eseguite nella finestra 2:

           (UPDLOCK)       (HOLDLOCK)    (UPDLOCK, HOLDLOCK)    (TABLOCKX)
---------------------------------------------------------------------------
SELECT    not blocked      not blocked       not blocked         blocked
INSERT    not blocked        blocked           blocked           blocked
UPDATE      blocked          blocked           blocked           blocked
DELETE      blocked          blocked           blocked           blocked

Ho frainteso le risposte fornite in quelle domande o ho commesso un errore durante il test? In caso contrario, perché dovresti usare (UPDLOCK, HOLDLOCK)vs. (HOLDLOCK)da solo?


Ulteriore spiegazione di ciò che sto cercando di realizzare:

Vorrei selezionare le righe da una tabella e impedire che i dati in quella tabella vengano modificati durante l'elaborazione. Non sto modificando quei dati e vorrei consentire le letture.

Questa risposta dice chiaramente che (UPDLOCK, HOLDLOCK)bloccherà le letture (non quello che voglio). I commenti su questa risposta implicano che è HOLDLOCKquello che impedisce le letture. Per cercare di capire meglio gli effetti dei suggerimenti della tabella e vedere se UPDLOCKda solo avrebbe fatto quello che volevo, ho fatto l'esperimento sopra e ho ottenuto risultati che contraddicono quelle risposte.

Attualmente, credo che (HOLDLOCK)sia quello che dovrei usare, ma temo di aver commesso un errore o di aver trascurato qualcosa che tornerà a mordermi in futuro, da qui questa domanda.

Risposte:


102

Perché il blocco UPDLOCK seleziona? La matrice di compatibilità dei blocchi mostra chiaramente Nper la contesa S / U e U / S, come in No Conflict .

Per quanto riguarda il suggerimento HOLDLOCK, la documentazione afferma:

HOLDLOCK: equivale a SERIALIZZABILE. Per ulteriori informazioni, vedere SERIALIZZABILE più avanti in questo argomento.

...

SERIALIZZABILE: ... La scansione viene eseguita con la stessa semantica di una transazione in esecuzione al livello di isolamento SERIALIZZABILE ...

e l' argomento Livello di isolamento della transazione spiega cosa significa SERIALIZZABILE:

Nessun'altra transazione può modificare i dati che sono stati letti dalla transazione corrente fino al completamento della transazione corrente.

Altre transazioni non possono inserire nuove righe con valori chiave che rientrerebbero nell'intervallo di chiavi lette da qualsiasi istruzione nella transazione corrente fino al completamento della transazione corrente.

Pertanto il comportamento che vedi è perfettamente spiegato dalla documentazione del prodotto:

  • UPDLOCK non blocca SELECT o INSERT simultanei, ma blocca qualsiasi UPDATE o DELETE delle righe selezionate da T1
  • HOLDLOCK significa SERALIZZABILE e quindi permette SELEZIONI, ma blocca AGGIORNAMENTI e CANCELLAZIONI delle righe selezionate da T1, così come qualsiasi INSERTO nel range selezionato da T1 (che è l'intera tabella, quindi qualsiasi inserto).
  • (UPDLOCK, HOLDLOCK): il tuo esperimento non mostra cosa bloccherebbe oltre al caso precedente, ovvero un'altra transazione con UPDLOCK in T2 :
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX non necessita di spiegazioni

La vera domanda è cosa stai cercando di ottenere ? Giocare con i suggerimenti di blocco senza una comprensione assoluta e completa del 110% della semantica di blocco è implorare problemi ...

Dopo la modifica OP:

Vorrei selezionare le righe da una tabella e impedire che i dati in quella tabella vengano modificati durante l'elaborazione.

È necessario utilizzare uno dei livelli di isolamento delle transazioni più elevati. REPEATABLE READ impedisce la modifica dei dati letti. SERIALIZABLE impedirà i dati che si leggono vengano modificati e nuovi dati vengano inseriti. L'utilizzo dei livelli di isolamento delle transazioni è l'approccio giusto, invece di utilizzare i suggerimenti per le query. Kendra Little ha un bel poster che spiega i livelli di isolamento .


+1 e grazie per la risposta dettagliata. Aggiornerò la mia domanda per aggiungere i dettagli di quale sia il mio obiettivo.
Jeff Ogata

1
@ Remus Rusanu potresti spiegare perché l'approccio giusto utilizza i livelli di isolamento anziché i suggerimenti per le query? Ho una procedura in cui devo solo bloccare la modifica di due tabelle e sto usando TABLOCK, HOLDLOCK, devo davvero passare al livello di isolamento e bloccare tutte le tabelle nella mia transazione?
Steve

Mi piacerebbe una spiegazione per TABLOCKX :)
niico

Nota: il collegamento per l'inserimento nel blog di Kendra Little restituisce un 404. Non riesco a trovare alcuna voce datata 2 febbraio 2011, come suggerisce il collegamento.
Bacon Bits

22

UPDLOCK viene utilizzato quando si desidera bloccare una o più righe durante un'istruzione select per un'istruzione di aggiornamento futura. Il futuro aggiornamento potrebbe essere la prossima dichiarazione nella transazione.

Altre sessioni possono ancora vedere i dati. Semplicemente non possono ottenere blocchi che non siano compatibili con UPDLOCK e / o HOLDLOCK.

Si utilizza UPDLOCK quando si desidera impedire ad altre sessioni di modificare le righe bloccate. Limita la loro capacità di aggiornare o eliminare le righe bloccate.

Si utilizza HOLDLOCK quando si desidera impedire ad altre sessioni di modificare i dati che si stanno guardando. Limita la loro capacità di inserire, aggiornare o eliminare le righe che hai bloccato. Ciò consente di eseguire nuovamente la query e visualizzare gli stessi risultati.


1
Grazie, ma non penso che tu abbia davvero risposto alla mia domanda: le risposte a quelle domande erano sbagliate nell'affermare che il (UPDLOCK,HOLDLOCK)blocco si legge, e c'è una ragione per usarle (UPDLOCK,HOLDLOCK)invece di solo (HOLDLOCK)?
Jeff Ogata

La mia seconda affermazione risponde alla tua domanda, sono sbagliati. Altre sessioni possono ancora leggere i dati.
Scott Bruns

Updlock, Holdlock non è la stessa cosa di holdlock. Updlock, holdlock blocca le righe per l'aggiornamento e serializza la transazione. Holdlock da solo serializza la transazione. Non blocca le righe selezionate per ulteriori accessi.
Scott Bruns

"UPDLOCK viene utilizzato quando si desidera bloccare una o più righe durante un'istruzione select per un'istruzione di aggiornamento futura." Adoro questo, dal momento che XLOCK potrebbe non funzionare a volte
Yiping
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.