2009-03-19 21 views
32

Tutta la documentazione sui deadlock di SQL Server parla dello scenario in cui l'operazione 1 blocca la risorsa A, quindi tenta di accedere alla risorsa B e l'operazione 2 blocca la risorsa B e tenta di accedere alla risorsa ASQL deadlock tra selezione/aggiornamento o selezione multipla

Tuttavia, vedo spesso deadlock tra una selezione e un aggiornamento o anche tra più selezioni in alcune delle nostre applicazioni occupate. Trovo che alcuni dei punti più fini dell'output deadlock trace siano piuttosto impenetrabili, ma mi piacerebbe davvero solo capire cosa può causare un deadlock tra due singole operazioni. Sicuramente se una select ha un lock di lettura l'aggiornamento dovrebbe solo aspettare prima di ottenere un lock esclusivo e viceversa?

Questo sta accadendo su SQL Server 2005, non penso che questo faccia la differenza.

risposta

11

una volta ho Aggiunto A buon articolo su Advanced SQL Server locking a SQL-Server-Performance.com. Questo articolo va oltre la classica situazione di stallo che hai menzionato e potrebbe darti qualche informazione sul tuo problema.

0

Dovresti leggere su di isolamento delle transazioni: http://msdn.microsoft.com/en-us/library/ms173763.aspx

+0

Sono a conoscenza dei livelli di isolamento, i deadlock precedenti possono essere risolti rendendo la selezione letta senza commit MA perché una lettura che inizia PRIMA di un aggiornamento finisce in un deadlock con quell'aggiornamento con read committed? –

1

Leggere correttamente su transazioni e livelli di isolamento: per un lavoro un po 'denso ma abbastanza completo e neutro dal punto di vista tecnologico, vedere Principles of Transaction Processing. Ha scosso il mio mondo (e mi ha dato parecchi mal di testa!).

Non sono sicuro di cosa si stia riscontrando o del livello di isolamento che si sta utilizzando. Ma considera questo: per tutto il motore di database sa, se tu leggi in una transazione, come può dire se vuoi scrivere più tardi? Elevati livelli di isolamento richiedono il blocco ogni volta che viene eseguita una lettura, probabilmente sull'intera tabella per proteggersi dalle letture fantasma, poiché i dati potrebbero influenzare una scrittura in un secondo momento.

Vuoi che il database attenda arbitrariamente un blocco esclusivo dei dati? Dai un'occhiata ai tuoi livelli di isolamento per tutto e se stai eseguendo inutilmente una serie di letture come una transazione isolata. Non è sempre facile determinare come sporca letture fallite si può tollerare, anche se ...

+2

Penso che la domanda dei posters fosse più specifica di una dilazione generale che i livelli di isolamento potrebbero curare. – eckes

+0

Non definirei esattamente PoTP come un rant. Rob ha chiesto specificamente aiuto nella comprensione della transazionalità e sembrava avere qualche problema a capire i compromessi coinvolti. Se sottolineando che la letteratura utile è inaffidabile, allora probabilmente sto schiumando sempre in bocca! YMMV. –

5

Locks tra le query singoli possono accadere come si bloccano le righe singole, non l'intera tabella:

La query di aggiornamento ottiene un aggiornamento sulla serratura poche righe in una tabella e la query di selezione ottiene un blocco di lettura su alcune altre righe nella tabella. La query di aggiornamento tenta quindi di ottenere un blocco di aggiornamento sulle righe che vengono lette bloccate e la query di selezione tenta di ottenere un blocco di lettura sulle righe che sono bloccate per l'aggiornamento.

Può diventare ancora più complicato con i blocchi di escalading, ovvero il database decide che ci sono troppe righe singole bloccate da una transazione in modo che sia necessario eseguire l'escalation per bloccare una sezione della tabella o l'intera tabella. Ciò significa che il blocco potrebbe influire sulle righe che non sono direttamente coinvolte nella query.

19

Ciò può accadere perché una selezione prende un blocco su due diversi indici, nel frattempo un aggiornamento prende un blocco sugli stessi indici nell'ordine opposto. La selezione ha bisogno di due indici perché il primo indice non copre tutte le colonne a cui ha bisogno di accedere; l'aggiornamento ha bisogno di due indici perché se si aggiorna la colonna chiave di un indice è necessario bloccarlo.

http://blogs.msdn.com/bartd/archive/2006/09/25/770928.aspx ha una spiegazione fantastica. Le correzioni suggerite includono l'aggiunta di un indice che copra tutte le colonne necessarie per selezionare, passare all'isolamento dello snapshot o forzare esplicitamente la selezione a prendere un blocco di aggiornamento che normalmente non avrebbe bisogno.

12

Sono sorpreso che nessuno abbia menzionato il suggerimento di blocco WITH (UPDLOCK). È molto utile se hai deadlock che coinvolgono ad es. due coppie select-insert in parallelo.

In SQL Server, se si seleziona il file con WITH (UPDLOCK), la seconda selezione attenderà fino al termine della prima selezione. In caso contrario, ottengono blocchi condivisi e, quando tentano simultaneamente di eseguire l'upgrade a blocchi esclusivi, si bloccano.

+0

'Rolf Kristensen' ha spiegato' WITH (UPDLOCK) 'perfettamente nella sua risposta. – Mahmoodvcs

4

La mia ipotesi è che l'istruzione select acquisisca un blocco di lettura, quando si arriva con la dichiarazione di aggiornamento, quindi è necessario eseguire l'aggiornamento a un write-lock.

L'aggiornamento a un blocco di scrittura richiede che tutti gli altri blocchi di lettura vengano rimossi (le loro transazioni di selezione sono completate). Ma se un altro processo ha già la brillante idea di passare a un write-lock, allora all'improvviso ci sono due processi che si aspettano l'un l'altro per rilasciare il blocco di lettura, in modo che possano ottenere il blocco di scrittura.

Se si utilizza select-for-update (UPDLOCK), acquisirà un blocco di scrittura dall'inizio e quindi non si verificherà il problema del deadlock.