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.
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
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
Non sempre una buona idea ... http: // sqlblogcasts .com/blog/tonyrogerson/archive/2006/11/16/1345.aspx – gbn