Ha un grande impatto.
Il blocco di aggiornamento richiede un blocco di aggiornamento sulla riga, l'aggiornamento di Intent sulla pagina e un blocco condiviso sulla tabella/database.
Ciò non impedisce ad altre query di accedere ai dati all'interno della tabella, poiché i blocchi sulla pagina/database sono puramente blocchi di condivisione. Semplicemente non possono interferire con i blocchi contro la singola riga/pagina/tabella tentando di eseguire un'operazione che contraddirebbe i blocchi. Se ciò si verificava, la richiesta si accodava dietro i blocchi correnti e aspettava che fosse disponibile prima che potesse procedere.
Utilizzando holdlock, la query viene forzata per essere serializzata, bloccando la tabella esclusivamente fino al completamento dell'azione. Ciò impedisce a chiunque di leggere la tabella a meno che non venga usato il suggerimento nolock, consentendo una lettura potenzialmente sporca.
Per vedere l'effetto, generare una tabella di esempio 'pippo' e inserire alcuni dati cestino in esso.
begin tran
select * from foo with (updlock)
where tableid = 1
-- notice there is no commit tran
Aprire un'altra finestra e provare:
select * from foo
Le righe tornano, ora il commit della transazione query originale. Re-eseguirlo alterata da utilizzare HOLDLOCK così:
begin tran
select * from foo with (updlock, holdlock)
where tableid = 1
Torna alla all'altra finestra e provare selezionare nuovamente i dati, la query non restituirà i valori dal momento che è bloccata dal blocco esclusivo. Conferma la transazione sulla prima finestra e i risultati della seconda query appariranno poiché non è più bloccato.
Il test finale consiste nell'utilizzare il nolock, eseguire nuovamente la transazione utilizzando updlock e holdlock. quindi eseguire il seguente nella seconda finestra:
select * from foo (nolock)
I risultati torneranno automaticamente, dal momento che avete accettato il rischio di una lettura sporca (leggi non impegnati).
Quindi è visto avere un grande impatto, nel senso che si stanno forzando le azioni su quel tavolo per essere serializzate che potrebbero essere ciò che si desidera (a seconda dell'aggiornamento in corso) o creerà un collo di bottiglia molto grande su quel tavolo . Se tutti lo facessero su una tabella occupata con transazioni di lunga durata, causerebbero ritardi significativi all'interno di un'applicazione.
Come tutte le funzionalità SQL, se utilizzate correttamente possono essere potenti, ma l'utilizzo errato di una funzionalità/suggerimento può causare problemi significativi. Preferisco utilizzare i suggerimenti come ultima risorsa per quando devo eseguire l'override del motore, non come approccio predefinito.
Modifica come richiesto: Testato in SQL 2005, 2008, 2008R2 (Tutte le imprese) - tutti installati su quasi tutte le impostazioni predefinite, database di test creato utilizzando tutti i valori predefiniti (è stato inserito solo il nome del DB).
ottima risposta, grazie – marijne
bella spiegazione, che aiuta molto! – Mercurybullet
@Darren - Ho eseguito il rollback della modifica apportata, nessun blocco non è l'impostazione predefinita e la seconda selezione non dovrebbe richiedere un blocco di aggiornamento. – Andrew