ho una stored procedure che esegue un join di TableB
a TableA
:Fix deadlock di SQL Server: forza l'ordine di join o riprovare automaticamente?
SELECT <--- Nested <--- TableA
Loop <--
|
---TableB
Allo stesso tempo, in una transazione, righe vengono inserite TableA
, e poi in TableB
.
Questa situazione è a volte causando situazioni di stallo, in quanto la stored procedure di selezione afferra le righe da TableB, mentre l'inserto aggiunge righe da TableA, e poi ognuno vuole l'altro di lasciar andare l'altra tabella:
INSERT SELECT
========= ========
Lock A Lock B
Insert A Select B
Want B Want A
....deadlock...
Logic richiede l'INSERT
aggiungere prima righe a, e poi a B, mentre io personalmente non mi interessa l'ordine in cui SQL Server esegue la sua iscriversi - finché si unisce.
La raccomandazione comune per la risoluzione dei deadlock è garantire che tutti accedano alle risorse nello stesso ordine. Ma in questo caso l'ottimizzatore di SQL Server mi sta dicendo che l'ordine opposto è "migliore". Posso forzare un altro ordine di join e avere una query con risultati peggiori.
Ma dovrei?
Devo eseguire l'override dell'ottimizzatore, ora e sempre, con un ordine di join che voglio utilizzarlo?
Oppure dovrei semplicemente intercettare l'errore nativo 1202 e inviare nuovamente l'istruzione select?
La domanda non è quanto peggio potrebbe essere la query quando eseguo l'override dell'ottimizzatore e perché faccia qualcosa di non ottimale. La domanda è: è meglio riprovare automaticamente, piuttosto che eseguire query peggiori?
Remus, riprovare letture ha perfettamente senso, ma riprovare automaticamente le scritture dopo deadlock porta a aggiornamenti persi. Quando scrivi e diventi una vittima del deadlock, è probabile che i dati che stai per toccare siano stati modificati da qualcun altro. Non dovremmo riscrivere automaticamente in questi casi. Dovremmo rileggere i dati eventualmente modificati e considerare nuovamente se vogliamo salvare. Ha senso? –
@AlexKuznetsov: Questo è assurdo, se una transazione è scritta correttamente (cioè atomicamente), allora come potrebbe ritentare che potrebbe causare un aggiornamento perso? Sto dando questo +1, è sicuramente la risposta giusta. Non puoi fermare ogni deadlock, è solo una parte del rumore di fondo con la semantica ACID. – Aaronaught
@Alex, @Aaro: in effetti hai entrambi ragione. Con "riprova" intendo davvero "leggi lo stato corrente, applica le modifiche, rispondi al nuovo stato". Per le applicazioni di elaborazione automatica, questo è un modello molto facile da ottenere. Tuttavia, per le applicazioni interattive degli utenti, questo può essere più difficile e spesso l'azione corretta consiste nel respingere la "scrittura" rileggendo lo stato corrente e re-visualizzarlo all'utente, in modo che lui/lei possa confermare che le modifiche applicate ha senso nel nuovo stato/contesto, e penso che questo fosse ciò che Alex aveva in mente. L'azione corretta dipende quindi da caso a caso. –