2011-01-03 12 views
14

Questa è davvero più una discussione che una domanda specifica su nolock.A NOLOCK o NOT a NOLOCK, questa è la domanda

Recentemente ho rilevato un'app che quasi tutte le query (e ce ne sono molte) hanno l'opzione nolock su di esse. Ora sono abbastanza nuovo per SQL server (usato Oracle per 10 anni), ma trovo questo piuttosto inquietante. Quindi questo weekend stavo parlando con uno dei miei amici che gestisce un sito di e-commerce piuttosto grande (il nome sarà trattenuto per proteggere i colpevoli) e dice che deve farlo con tutti i suoi server SQL perché finirà sempre in deadlock.

Si tratta semplicemente di una breve caduta con server SQL? Questo è solo un fallimento nel design del DB (il mio non è un terzo livello, ma è vicino) Qualcuno là fuori sta eseguendo un'applicazione SQL server senza nolocks? Questi sono problemi che Oracle gestisce meglio con più record di registrazione grandulare.

Il server SQL non è in grado di gestire grandi carichi? C'è qualche soluzione migliore di leggere i dati non trasmessi? Mi piacerebbe sentire cosa pensa la gente.

Grazie

risposta

13

SQL Server ha aggiunto snapshot isolation in SQL Server 2005, questo vi permetterà di leggere ancora l'ultimo valore corretto, senza dover attendere per serrature. StackOverflow utilizza anche l'isolamento dello snapshot. Il livello di isolamento dello snapshot è più o meno lo stesso utilizzato da Oracle, questo è il motivo per cui deadlock non sono molto comuni su una scatola Oracle. Basta essere consapevoli di avere un sacco di spazio tempdb se non effettuato

da Books On Line

Quando l'opzione di database READ_COMMITTED_SNAPSHOT è impostato su ON, leggere isolamento impegnata utilizza fila delle versioni per fornire statement- livello leggere la coerenza. Le operazioni di lettura richiedono solo serrature a livello di tavolo SCH-S e nessun blocco di pagina o di riga. Quando l'opzione READ_COMMITTED_SNAPSHOT del database è impostata su OFF, che è l'impostazione predefinita , l'isolamento impegnato si comporta come nelle precedenti versioni di SQL Server. Entrambe le implementazioni soddisfano la definizione ANSI dell'isolamento con read committed .

+0

Con un'istantanea attiva, quali sono le probabilità di imbattersi in un deadlock? Non ti suggerirei di darmi un pertcentage, ma ti sei mai imbattuto in una situazione di stallo quando è in esecuzione? – Limey

+0

Sembra aver risolto il problema di StackOverflow, io stesso non ho visto deadlock con esso, ma anche implementare alcune best practice in termini di programmazione server SQl che minimizza questo per iniziare con – SQLMenace

+0

Non sempre una buona idea ... http: // sqlblogcasts .com/blog/tonyrogerson/archive/2006/11/16/1345.aspx – gbn

4

No, non è necessario utilizzare NOLOCK. Link: SO 1

Per quanto riguarda il carico, abbiamo a che fare con 2000 righe al secondo, che è piccolo cambiamento rispetto a 35k TPS

deadlock sono causati da contese di blocco e di solito causati da ordine di scrittura incoerente sulle tavole nelle transazioni. Gli ORM sono specialmente spazzatura in questo. Li prendiamo molto di rado. Un DAL ben scritto dovrebbe riprovare anche secondo MSDN.

2

In un ambiente OLTP normalizzato tradizionale, NOLOCK è un odore di codice e quasi certamente non necessario in un sistema progettato correttamente.

In un modello dimensionale, ho utilizzato NOLOCK estesamente per evitare il blocco di tabelle di fatti e dimensioni molto grandi che venivano popolati con dati di fatto successivi (e le dimensioni potevano essere in scadenza). Nel modello dimensionale, i fatti non cambiano mai o non cambiano mai dopo un certo punto.Allo stesso modo, qualsiasi dimensione a cui viene fatto riferimento sarà anche statica, quindi ad esempio, NOLOCK interromperà la lunga operazione di analisi sui dati di ieri impedendo la scadenza di una dimensione durante il caricamento di dati per i dati di oggi.

11

Se qualcuno dice che senza NOLOCK la loro applicazione si blocca sempre, allora c'è (più che probabile) un problema con le loro domande. Un deadlock significa che due transazioni non possono procedere a causa di conflitto di risorse e il problema non può essere risolto. Un esempio:

Prendere in considerazione le transazioni A e B. Entrambi sono in volo. La transazione A ha inserito una riga nella tabella X e la transazione B ha inserito una riga nella tabella Y, quindi la transazione A ha un blocco esclusivo su X e la transazione B ha un blocco esclusivo su Y.

Ora, la transazione A deve eseguire un SELEZIONA rispetto alla tabella Y e Transazione B deve eseguire SELECT rispetto alla tabella X.

Le due transazioni sono bloccate in blocco: A ha bisogno della risorsa Y e B ha bisogno della risorsa X. Poiché nessuna transazione può procedere fino a quando l'altra non viene completata, la situta non può essere risolto: nessuna richiesta di transazioni per una risorsa può essere soddisfatta finché l'altra transazione non rilascia il blocco sulla risorsa in conflitto (ROLLBACK o COMMIT, non importa.)

SQL Server identifica questa situazione e seleziona una transazione o l'altra come vittima del deadlock, interrompe tale transazione e esegue il rollback, lasciando l'altra transazione libera per procedere al suo presumibile completamento.

I deadlock sono rari nella vita reale (IMHO). Uno di loro rettifica da

  • garantire che ambito della transazione è il più piccolo possibile, server di qualcosa di SQL fa automaticamente (ambito di transazione di default di SQL Server è una singola istruzione con un implicito COMMIT), e
  • garantire che le risorse di accesso transazioni nella stessa sequenza. Nell'esempio sopra, se le transazioni A e B bloccano entrambe le risorse X e Y nella stessa sequenza, non ci sarebbe un deadlock.

Timeout

un timeout, d'altra parte, si verifica quando una transazione supera il suo tempo di attesa e viene eseguito il rollback a causa di conflitti di risorse. Ad esempio, la Transazione A richiede la risorsa X. La Risorsa X è bloccata dalla Transazione B, quindi la Transazione A attende il rilascio del blocco. Se il blocco non viene rilasciato entro il limite di timeout delle query, la transazione in attesa viene interrotta e ripristinata. Ogni query ha un timeout di query associato (il valore predefinito è 30 secondi, credo), dopo di che la transazione viene interrotta e ripristinata. Il timeout della query può essere impostato su 0, nel qual caso SQL Server lascerà la query in attesa per sempre.

Questo è probabilmente quello di cui stanno parlando. Nella mia esperienza, i timeout di questo tipo si verificano di solito in grandi database quando lavori batch di grandi dimensioni aggiornano migliaia e migliaia di record in un'unica transazione, sebbene possano verificarsi perché una transazione va a lungo (connettersi al database di produzione in Query Abalyzer, eseguire BEGIN TRANSACTION, aggiorna una singola riga in una tabella di risultati frequenti in Query Analyzer e vai a pranzo senza eseguire ROLLBACK o COMMIT TRANSACTION e vedere quanto tempo impiega gli addetti alla produzione a farsi le scimmie ** t su di te.Non chiedetemi come lo so)

Questo tipo di timeout è di solito quello che si traduce in schizzi SQL perfettamente innocente con tutti i tipi di NOLOCK accenna

[SUGGERIMENTO: se la vostra intenzione di farlo, basta esegui SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED come prima dichiarazione nella stored procedure e lo hai fatto.]

Il problema con questo approccio (NOLOCK/READ UNCOMMITTED) è che puoi leggere dati non salvati da un'altra transazione: roba che è incompleto o potrebbe essere ripristinato in un secondo momento, quindi l'integrità dei dati è comprimibile. Potresti inviare una bolletta in base a dati con un livello elevato di follia.

La mia regola generale è che si dovrebbe evitare l'uso di suggerimenti tabella nella misura del possibile. Lascia che SQL Server e il suo Query Optimizer svolgano il loro lavoro.

Il modo giusto per evitare questo tipo di problema è evitare il tipo di transazioni (inserire un milione di righe tutte in un colpo solo, ad esempio) che causano i problemi. La strategia di blocco implicita nel database relazionale SQL è progettata attorno a piccole transazioni di breve portata. Il blocco deve essere di dimensioni ridotte e di breve durata. Pensa che "il cassiere della banca aggiorna il conto corrente di qualcuno con un deposito". come il caso d'uso sottostante. Progetta i tuoi processi in modo che funzionino in quel modello e sarai molto più felice fino in fondo.

Invece di inserire un milione di righe in una istruzione di inserimento mondo, eseguire il lavoro in blocchi indipendenti e eseguire il commit di ogni blocco in modo indipendente. Se il tuo inserto milioni di righe muore dopo aver elaborato 999.000 righe, tutto il lavoro svolto viene perso (per non parlare del fatto che il rollback può essere ab * tch e la tabella è ancora bloccata durante il rollback). Se inserisci il milione di righe nel blocco di 1000 righe ciascuna, che si attivano dopo ogni blocco, si evita la contesa del blocco che causa deadlock, poiché i blocchi verranno ottenuti e rilasciati e le cose continueranno a muoversi. Se qualcosa va a sud nel 999 ° blocco di 1000 righe e la transazione viene interrotta e ripristinata, hai ancora inserito 998.000 righe; hai perso solo 1000 righe di lavoro. Riavvia/Riprova è molto più semplice.

Inoltre, l'escalation dei blocchi si verifica nelle transazioni di grandi dimensioni. Per quanto riguarda l'effiency, le serrature escalation ad un ambito sempre più grande man mano che aumenta il numero di blocchi trattenuti dalla transazione. Se una singola transazione inserisce/aggiorna/elimina una singola riga in una tabella, ottengo un blocco di riga. Continuate a farlo e una volta che il numero di blocchi di riga trattenuti da quella transazione rispetto a quella tabella raggiunge un valore di soglia, SQL Server intensificherà la strategia di blocco: i blocchi di riga verranno consolidati e convertiti in blocchi di numero inferiore, aumentando così l'ambito di le serrature trattenute Da quel momento in avanti, un inserimento/eliminazione/aggiornamento di una singola riga bloccherà quella pagina nella tabella. Una volta che il numero di blocchi di pagine trattenuti raggiunge il suo valore di soglia, i blocchi di pagine vengono nuovamente consolidati e la strategia di blocco viene spostata ai blocchi di tabella: la transazione ora blocca l'intera tabella e nessun altro può giocare finché la transazione non esegue il commit o il rollback.

Se si può evitare di evitare funzionalmente l'uso di NOLOCK/READ UNCOMMITTED dipende interamente dalla natura dei processi che colpiscono il database sottostante (e dalla cultura dell'organizzazione che lo possiede).

Io stesso, cerco di evitarne l'uso il più possibile.

Spero che questo aiuti.

+0

Grazie! Penso che aggiunga una buona informazione alla discussione. – Limey

1

È necessario utilizzare solo nolock su un tavolo immutabile. Naturalmente, questo sarà lo stesso di Read Committed Snapshot. Senza lo snapshot, si risparmia solo il tempo necessario per applicare un blocco condiviso e quindi per rimuoverlo, che per la maggior parte dei casi non è necessario.

Come per un fasciatoio ... Nessun blocco non significa solo ottenere una riga prima che una transazione sia terminata aggiornando tutte le sue file. È possibile ottenere dati fantasma quando le pagine di dati si suddividono o persino le pagine di indice vengono suddivise. O nessun dato. Questo da solo mi ha spaventato, ma penso che ci possano essere ancora più scenari in cui si ottengono semplicemente dati sbagliati.

Ovviamente, nolock per ottenere stime approssimative o semplicemente effettuare il check-in di un processo potrebbe essere ragionevole.

Regola di base: se ci si preoccupa dei dati e i dati cambiano, non utilizzare NoLOCK.

+0

Noggins: non sono i dati che devono essere banali; è la richiesta dei dati. Ho dato due esempi - stime, o per ottenere qualche tipo di idea su dove ti trovi. Quindi il dato/processo potrebbe essere, e sarebbe, totalmente necessario. Ma questi casi d'uso particolari per la lettura potrebbero farlo con nolock dato che non userete i dati per progettare una bomba atomica o qualcosa del genere. Sto solo registrando. –

Problemi correlati