La pratica NOLOCK (suggerimento SQL Server) è una cattiva pratica?


125

Mi occupo di realizzare siti Web e applicazioni che non sono mission-critical -> ad es. software bancario, volo spaziale, applicazione di monitoraggio di terapia intensiva, ecc. L'idea è stata presa.

Quindi, con questo enorme disclaimer, è male usare il suggerimento NOLOCK in qualche istruzione Sql? Un certo numero di anni fa, è stato suggerito da un altro amministratore di SQL che dovrei usare NOLOCK se sono contento di una "lettura sporca" che mi darà un po 'più di prestazioni dal mio sistema perché ogni lettura non blocca il riga / tabella / qualunque cosa.

Mi è stato anche detto che è un'ottima soluzione se sto sperimentando dead-lock. Quindi, ho iniziato a seguire questo pensiero per alcuni anni fino a quando un guru Sql mi stava aiutando con un po 'di codice casuale e ho notato tutti i NOLOCK nel mio codice sql. Sono stato educatamente rimproverato e ha cercato di spiegarmelo (perché non è una buona cosa) e mi sono perso. Ho sentito che l'essenza della sua spiegazione era 'è una soluzione di cerotto per un problema più serio .. specialmente se stai vivendo un deadlock. Pertanto, risolvi la radice del problema ".

Recentemente ho fatto qualche google su questo e mi sono imbattuto in questo post .

Quindi, alcuni sensei di sql db guru possono per favore illuminarmi?


Non capisco Sam, stai dicendo di usare l'isolamento Snapshot se si tratta di un sito Web di lettura pesante. Ma poi stai dicendo che è stato così, ed è male? o solo il loro uso di NOLOCK?
Pure.Krome,

Risposte:


67

Con il suggerimento NOLOCK, il livello di isolamento della transazione per l' SELECTistruzione è READ UNCOMMITTED. Ciò significa che la query potrebbe visualizzare dati sporchi e incoerenti.

Questa non è una buona idea da applicare come regola. Anche se questo comportamento di lettura sporca è OK per l'applicazione basata su Web mission-critical, una scansione NOLOCK può causare un errore 601 che interromperà la query a causa del movimento dei dati a causa della mancanza di protezione del blocco.

Suggerisco di leggere Quando l'isolamento dello snapshot aiuta e quando fa male - MSDN consiglia di utilizzare SNAPSHOT LEGGI IMPEGNATO anziché SNAPSHOT nella maggior parte dei casi.


1
Rex, non esitare ad aggiungere una nota sull'isolamento dell'istantanea.
Sam Saffron,

2
Sì, Sam sta dicendo l'isolamento dell'istantanea e tu stai suggerendo Leggi l'istantanea commessa. Sto diventando così confuso: P (e devo ancora approfondire gli articoli!)
Pure.Krome

2
Occasionalmente è utile, ma normalmente non per la produzione. Lo uso spesso per estrarre un campione di dati da testare o per generare report in cui mi preoccupo principalmente di un ordine di grandezza approssimativo in cui una lettura sporca non ha importanza.
TimothyAWiseman

NOLOCK == Non mi interessa se mancano le righe impegnate, le righe non impegnate sono incluse, in rari casi la stessa riga viene restituita più di una volta e in casi molto rari vengono restituite righe che non corrispondono alla mia query. (vedi blogs.msdn.com/b/sqlcat/archive/2007/02/01/… , trovato da un altro SO q'n su questo argomento)
Andrew Hill,

106

Prima di lavorare su Stack Overflow, ero contrario NOLOCKal principio che potresti potenzialmente eseguire un SELECTcon NOLOCKe ottenere risultati con dati che potrebbero essere obsoleti o incoerenti. Un fattore a cui pensare è il numero di record che possono essere inseriti / aggiornati contemporaneamente mentre un altro processo sta selezionando i dati dalla stessa tabella. Se ciò accade molto, c'è un'alta probabilità di deadlock a meno che non si usi una modalità di database come READ COMMITED SNAPSHOT.

Da allora ho cambiato il mio punto di vista sull'uso NOLOCKdopo aver assistito a come può migliorare le SELECTprestazioni ed eliminare i deadlock su un SQL Server caricato in modo massiccio. A volte potresti non preoccuparti che i tuoi dati non siano esattamente impegnati al 100% e che tu abbia bisogno di risultati rapidamente anche se potrebbero non essere aggiornati.

Ponetevi una domanda quando pensate di usare NOLOCK:

La mia query include una tabella che ha un numero elevato di comandi INSERT/ UPDATEe mi interessa se i dati restituiti da una query potrebbero mancare queste modifiche in un determinato momento?

Se la risposta è no, utilizzare NOLOCKper migliorare le prestazioni.


Ho appena eseguito una rapida ricerca della NOLOCKparola chiave all'interno della base di codice per Stack Overflow e ho trovato 138 istanze, quindi la usiamo in parecchi punti.


7
IMO, questo è un po 'semplicistico. I deadlock possono essere rimossi usando gli indici di copertura, eliminando la pressione dall'indice cluster.
Mitch Wheat,

8
Non desidero ridurre l'importanza di una buona copertura dell'indice. A volte le query che utilizzano NOLOCK possono aggiungere prestazioni aggiuntive oltre ai guadagni realizzati dagli indici su tabelle con un numero elevato di inserimenti / aggiornamenti. La velocità delle query su Stack Overflow è fondamentale anche a costo di dati imprecisi o mancanti.
Geoff Dalgas

9
Apparentemente si possono ottenere file duplicate usando NOLOCK. Questo significa che devo sottovalutare la tua risposta. Scusate.
ErikE

1
@MitchWheat A SELECT, che legge solo da un indice di copertura, può causare un deadlock. SPID 1) inizia a SELECTdall'indice di copertura. SPID 2) Avvia uno UPDATEdella tabella. Aggiorna quindi passa all'aggiornamento dell'indice di copertura. UPDATEraggiunge un intervallo di indice bloccato da SELECTe diventa bloccato. SPID 1) continua a cercare attraverso l'indice di copertura, trova un intervallo bloccato da UPDATEe diventa bloccato. DEADLOCK . Niente può risolvere questo deadlock (tranne la cattura dell'errore SQL Server 1205 e il tentativo automatico o l'utilizzo NOLOCK)
Ian Boyd

2
Penso che la cosa importante da notare su questa risposta sia che era appropriato per il problema in questione . A seconda dell'applicazione, il rischio di dati non aggiornati / non confermati / duplicati / mancanti potrebbe non valere il compromesso.
Sviluppatore olistico,

20

Se non ti interessano le letture sporche (cioè in una situazione di LEGGENZA prevalentemente), NOLOCKva bene.

MA tieni presente che la maggior parte dei problemi di blocco è dovuta al fatto di non avere gli indici "corretti" per il carico di lavoro della tua query (supponendo che l'hardware sia all'altezza dell'attività).

E la spiegazione del guru era corretta. Di solito è una soluzione di cerotto per un problema più grave.

Modifica : sicuramente non sto suggerendo di usare NOLOCK. Immagino che avrei dovuto renderlo evidente. (Lo userei sempre e solo, in circostanze estreme in cui avevo analizzato che andava bene). Ad esempio, qualche tempo fa ho lavorato su alcuni TSQL che erano stati cosparsi di NOLOCK per cercare di alleviare i problemi di blocco. Li ho rimossi tutti, ho implementato gli indici corretti e TUTTI i deadlock sono andati via.


3
Hmm .. Ancora non capisco. Quindi va bene, ma è anche una forma scadente ... è questo che stai dicendo?
Pure.Krome,

Partendo dal presupposto che non ti interessi MAI alle letture sporche, non ti farà male. MA di solito si tratta di trattare il sintomo e non la causa ...
Mitch Wheat,

2
Beh, non penso che il suo giusto rexem sia stato appena declassato, penso che tu non abbia affrontato gli errori arbitrari che si manifestano quando usi nolock. Non va bene ottenere una pagina di errore vuota di tanto in tanto sul tuo sito Web, è davvero una forma scadente. Non mi piace l'affermazione che "se non ti preoccupi delle letture sporche, va bene" ... non va bene, anche se non ti importa delle letture sporche
Sam Saffron,

La pagina vuota che ottieni quando una query genera un'eccezione per la quale non hai implementato la logica di nuovo tentativo. Cosa succede sui tuoi siti quando l'esecuzione della query risulta con un'eccezione, hai tentativi di logica ovunque?
Sam Saffron,

Prendi una query molto ben ottimizzata che sai che sta colpendo gli indici corretti. Quindi aggiungi i suggerimenti di Nolock e guardalo diventare più veloce. Se non ti interessano le letture sporche non ti farai mai del male usando nolock.
Hardwareguy,

13

Dubbio era un "guru" che aveva avuto qualche esperienza nel traffico intenso ...

I siti Web sono generalmente "sporchi" quando la persona visualizza la pagina completamente caricata. Considera un modulo che viene caricato dal database e quindi salva i dati che vengono modificati ?? È idiota il modo in cui le persone continuano a leggere letture sporche come un no no.

Detto questo, se hai un numero di livelli in costruzione sulla tua selezione, potresti creare una pericolosa ridondanza. Se hai a che fare con scenari di denaro o di stato, allora non hai solo bisogno di leggere / scrivere dati transazionali, ma una soluzione di concorrenza adeguata (qualcosa che la maggior parte dei "guru" non si preoccupa).

D'altra parte, se hai una ricerca avanzata di prodotti per un sito Web (ovvero qualcosa che probabilmente non verrà memorizzato nella cache e sarà un po 'intensivo) e hai mai creato un sito con più di alcuni utenti simultanei (fenomenale quante "esperti" no), è ridicolo imitare il collo di ogni altro processo dietro di esso.

Sapere cosa significa e usarlo quando appropriato. Il database sarà quasi sempre il collo di bottiglia principale in questi giorni ed essere furbi sull'uso di NOLOCK può farti risparmiare migliaia di infrastrutture.

EDIT: Non è solo deadlock con cui aiuta, è anche quanto farai aspettare tutti fino a quando hai finito, o viceversa.

Utilizzo del suggerimento NOLOCK in EF4?


10

Nessuna delle risposte è sbagliata, anche se forse un po 'confusa.

  • Quando si eseguono query su singoli valori / righe è sempre una cattiva pratica utilizzare NOLOCK: probabilmente non si desidera mai visualizzare informazioni errate o magari intraprendere qualsiasi azione su dati errati.
  • Quando si visualizzano informazioni statistiche approssimative, NOLOCK può essere molto utile. Prendi SO come esempio: sarebbe una sciocchezza prendere i lucchetti per leggere il numero esatto di visualizzazioni di una domanda o il numero esatto di domande per un tag. A nessuno importa se affermi erroneamente 3360 domande taggate con "sql-server" ora e, a causa di un rollback della transazione, 3359 domande un secondo dopo.

Non sono affatto d'accordo con il tuo primo punto. SE stai interrogando singoli valori / righe e stai specificando un ID univoco per quella riga e sai che nessun altro processo accederà ad esso, quindi l'utilizzo di nolock è perfettamente accettabile e riduce il blocco in un'applicazione concorrente.
tuseau,

1
No non lo è. La riga potrebbe cambiare per altri motivi, ad esempio inserendo un'altra riga si divide la pagina. L'indicizzazione corretta, l'istantanea con commit della lettura e l'isolamento dell'istantanea sono quasi sempre idee migliori.
Mark Sowul,

1
@tuseau se "sai" che nessun altro processo accederà alla riga, l'atto di prendere un lucchetto non bloccherà nulla, quindi non ti costa (praticamente) nulla,
Andrew Hill

2

Come sviluppatore professionista direi che dipende. Ma seguirò sicuramente i consigli di GATS e OMG Ponies. Sapere cosa stai facendo, sapere quando aiuta e quando fa male e

leggere suggerimenti e altre idee sbagliate

cosa potrebbe farti capire meglio il server sql. In genere seguo la regola secondo cui i suggerimenti SQL sono MALE, ma sfortunatamente li uso di tanto in tanto quando sono stufo di forzare il server SQL a fare le cose ... Ma questi sono casi rari.

luke


2

Quando il supporto delle app voleva rispondere alle query di ad-hock dal server di produzione utilizzando SSMS (che non era soddisfatto tramite report), ho richiesto che usassero nolock. In questo modo l'attività "principale" non è interessata.


2

Concordo con alcuni commenti sul suggerimento di NOLOCK e in particolare con quelli che dicono "usalo quando è appropriato". Se l'applicazione è scritta male e utilizza un modo inappropriato della concorrenza, ciò potrebbe causare l'escalation del blocco. Anche le tabelle altamente transazionali vengono bloccate continuamente a causa della loro natura. Avere una buona copertura dell'indice non aiuterà a recuperare i dati, ma l'impostazione di ISOLATION LEVEL su READ UNCOMMITTED lo fa. Inoltre, credo che l'utilizzo del suggerimento NOLOCK sia sicuro in molti casi in cui la natura delle modifiche è prevedibile. Ad esempio: nella produzione quando i lavori con i viaggiatori stanno attraversando processi diversi con molti inserti di misurazioni, è possibile eseguire in modo sicuro query sul lavoro finito con il suggerimento NOLOCK e in questo modo evitare collisioni con altre sessioni che mettono blocchi PROMOTATI o ESCLUSIVI sul tavolo /pagina. I dati a cui accedi in questo caso sono statici, ma potrebbero risiedere in una tabella molto transazionale con centinaia di milioni di record e migliaia di aggiornamenti / inserimenti al minuto. Saluti


2

Credo che virtualmente non sia mai corretto usare nolock.

Se stai leggendo una singola riga, l'indice corretto significa che non avrai bisogno di NOLOCK poiché le singole azioni di riga vengono completate rapidamente.

Se stai leggendo molte righe per qualcosa di diverso dalla visualizzazione temporanea e ti preoccupi di poter ripetere il risultato o difenderti dal numero prodotto, NOLOCK non è appropriato.

NOLOCK è un tag surrogato per "Non mi interessa se questa risposta contiene righe duplicate, righe che vengono eliminate o righe che non sono mai state inserite per iniziare a causa del rollback"

Errori possibili in NOLOCK:

  • Le righe che corrispondono non vengono affatto restituite.
  • le singole righe vengono restituite più volte (incluse più istanze della stessa chiave primaria)
  • Vengono restituite le righe che non corrispondono.

Qualsiasi azione che può causare una divisione della pagina mentre è in esecuzione la selezione noLock può causare queste cose. Quasi ogni azione (anche un'eliminazione) può causare una divisione della pagina.

Pertanto: se "sai" che la riga non verrà modificata durante l'esecuzione, non utilizzare nolock, poiché un indice consentirà un recupero efficiente.

Se sospetti che la riga possa cambiare mentre la query è in esecuzione e ti preoccupi della precisione, non utilizzare nolock.

Se si considera NOLOCK a causa di deadlock, esaminare la struttura del piano di query per scansioni di tabelle impreviste, tracciare i deadlock e vedere perché si verificano. NOLOCK intorno alle scritture può significare che le query precedentemente bloccate potenzialmente potrebbero entrambi scrivere la risposta sbagliata.


2

Le soluzioni migliori, quando possibile, sono:

  • Replica i tuoi dati (usando la replica dei log) in un database di report.
  • Utilizzare le snapshot SAN e montare una versione coerente del DB
  • Utilizzare un database con un livello di isolamento delle transazioni fondamentale migliore

Il livello di isolamento delle transazioni SNAPSHOT è stato creato perché MS stava perdendo le vendite a Oracle. Oracle utilizza i log di annullamento / ripetizione per evitare questo problema. Postgres utilizza MVCC. In futuro, MS Heckaton utilizzerà MVCC, ma a distanza di anni dalla produzione è pronta.


C'è un errore di battitura sopra. Intendo dire "un migliore meccanismo di isolamento delle transazioni fondamentali".
partire dal

1
Il livello di isolamento delle transazioni SNAPSHOT è un'invenzione di MS. Fondamentalmente inserisce i dati in una tabella temporanea in TEMPDB. Quel DB è condiviso tra tutti i DB sulla scatola. Quindi, vorrai usare SSD per TEMPDB quando possibile. Questo è probabilmente meno sforzo rispetto alle altre opzioni.
partire dal

1

NOLOCK è spesso sfruttato come un modo magico per accelerare le letture del database, ma cerco di evitare di usarlo il più possibile.

Il set di risultati può contenere righe non ancora impegnate, che spesso vengono successivamente ripristinate.

Un errore o un set di risultati può essere vuoto, mancare righe o visualizzare la stessa riga più volte.

Questo perché altre transazioni stanno spostando i dati mentre li stai leggendo.

READ COMMITTED aggiunge un ulteriore problema in cui i dati sono danneggiati all'interno di una singola colonna in cui più utenti cambiano la stessa cella contemporaneamente.


-2

Nella vita reale in cui si incontrano sistemi già scritti e l'aggiunta di indici alle tabelle, quindi si rallenta drasticamente il caricamento dei dati di una tabella di dati da 14 gig, a volte si è costretti a utilizzare WITH NOLOCK nei report e a eseguire la prova di fine mese in modo che le funzioni aggregate (somma , conteggio ecc.) non eseguire il blocco di righe, pagine, tabelle e scoraggiare le prestazioni complessive. Facile da dire in un nuovo sistema, non utilizzare mai WITH NOLOCK e utilizzare gli indici, ma l'aggiunta di indici riduce notevolmente il caricamento dei dati e, quando mi viene detto, quindi, alterare la base di codice per eliminare gli indici, quindi caricare in blocco quindi ricreare gli indici - che va tutto bene, se stai sviluppando un nuovo sistema. Ma non quando hai già un sistema in atto.


1
cosa stai dicendo
Max Alexander Hanna,
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.