Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Confuso su UPDLOCK, HOLDLOCK

Perché UPDLOCK dovrebbe bloccare le selezioni? La matrice di compatibilità dei blocchi mostra chiaramente N per la contesa S/U e U/S, come in Nessun conflitto .

Per quanto riguarda l'hint HOLDLOCK la documentazione afferma:

HOLDLOCK:equivale a SERIALIZABLE. Per ulteriori informazioni, consulta SERIALIZABLE più avanti in questo argomento.

...

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

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

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 rientrino 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 né INSERT simultanei, ma blocca qualsiasi UPDATE o DELETE delle righe selezionate da T1
  • HOLDLOCK significa SERALIZABILE e quindi consente SELECTS, ma blocca UPDATE ed DELETE delle righe selezionate da T1, anche come qualsiasi INSERT nell'intervallo selezionato da T1 (che è l'intera tabella, quindi qualsiasi inserire).
  • (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 c'è bisogno di spiegazioni

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

Dopo la modifica dell'OP:

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

Dovresti utilizzare uno dei livelli di isolamento delle transazioni più elevati. LETTURA RIPETIBILE impedirà la modifica dei dati letti. SERIALIZABLE impedirà la modifica dei dati letti e nuovi dati dall'inserimento. L'utilizzo dei livelli di isolamento delle transazioni è l'approccio corretto, al contrario dell'utilizzo dei suggerimenti per le query. Kendra Little ha un bel poster che spiega i livelli di isolamento.