Nell'ambito della serie autunnale dei giorni di formazione del database di Quest, Brent Ozar, Microsoft Certified Master ha presentato un tutorial su "Evitare i deadlock con l'ottimizzazione delle query". Il programma si è concentrato sui tre problemi di concorrenza che si verificano in SQL Server, tre modi per risolverli e un modo che sembra risolverli, ma in realtà non è così.
Problemi di concorrenza:blocco, blocco e deadlock in SQL Server
Quali sono i problemi di concorrenza? Si verificano quando le query cercano di evitare conflitti tra loro su oggetti di database come le tabelle. Sono:
- Blocco – Le query lo fanno continuamente per impedire ad altre query di utilizzare una tabella contemporaneamente. Questa è una normale operazione di database.
- Blocco – Ciò si verifica quando una query ha un blocco normale, ma un'altra query tenta di acquisire lo stesso blocco. La seconda query deve attendere il tempo necessario affinché la prima query rilasci il blocco. A seconda della natura della prima query, la seconda potrebbe attendere un tempo molto breve o molto lungo. Sono quelle lunghe attese che influiscono davvero sulle prestazioni.
- Deadlock – I deadlock si verificano quando una query accetta un blocco, un'altra query richiede un blocco diverso e quindi ciascuna desidera acquisire il blocco dell'altra. SQL Server risolve questo problema designando una delle query come vittima e uccidendola per interrompere la situazione di stallo. Anche se una delle query è in grado di procedere, ciò ha anche un impatto sulle prestazioni.
Risoluzione dei problemi di concorrenza
Indipendentemente dal fatto che tu stia riscontrando blocchi o deadlock in SQL Server, ci sono modi per risolvere i problemi di concorrenza. Brent ha presentato questi tre metodi e ha trascorso la maggior parte del resto della sessione concentrandosi sul secondo, ovvero correggere il codice errato.
- Disponi di indici sufficienti per velocizzare le tue query, ma non così tanti da rallentare le cose facendo sì che le query mantengano più blocchi per periodi di tempo più lunghi
- Ottimizza il tuo codice transazionale in modo che le query funzionino attraverso le tabelle nello stesso ordine prevedibile ogni volta
- Utilizza il giusto livello di isolamento per le esigenze della tua applicazione
Mentre è entrato nella parte pratica del programma, Brent ha commentato l'utilizzo delle istruzioni NOLOCK per il blocco e il deadlock. Ha avvertito che NOLOCK non risolve davvero questi problemi perché si basa su "letture sporche" - essenzialmente, ignora i blocchi di riga di altre query.
Nella sua dimostrazione di ciò utilizzando il database Stack Overflow, ha creato una semplice query che cercava e contava persone chiamate "Alex". Quindi, ha creato un'altra query che avrebbe eseguito un aggiornamento sulle persone che non sono state chiamato Alex:nessun inserimento o eliminazione di record. Una query non dovrebbe avere nulla a che fare con l'altra. Ma, eseguirli insieme porta a risultati diversi nel numero di persone di nome Alex. Questo perché NOLOCK ti consente di vedere i dati che non sono stati impegnati, portando a risultati casuali che non puoi prevedere. Succede solo in simultanea.
Chiaramente, è necessaria una soluzione migliore per il blocco e il deadlock in SQL Server che non porti a risultati casuali e imprevedibili.
Una soluzione migliore per i deadlock SQL
Brent ha quindi dimostrato come risolvere un deadlock modificando il codice che lo causa. La sua prima demo mostrava una semplice situazione che coinvolgeva due tavoli in modo che il pubblico potesse vedere un deadlock al rallentatore mentre si verificava. Poiché SQL Server cerca i deadlock ogni 5 secondi ed elimina la query di cui è più facile eseguire il rollback, siamo stati in grado di vedere emergere la vittima del deadlock.
In una situazione semplice, si applica il consiglio più generale, ovvero di toccare le tabelle nello stesso ordine ogni volta quando si costruiscono le query. Questo generalmente impedirà alle query di bloccarsi a vicenda.
E per le query più complesse? Per questo scenario, Brent ha utilizzato una situazione più realistica che potrebbe facilmente sorgere su Stack Overflow in cui due persone votano a vicenda le domande. Poiché gli stessi utenti sono coinvolti in entrambe le transazioni, ciò provoca un deadlock.
Qui, non è sufficiente elaborare ogni tabella nello stesso ordine ogni volta, ma è anche necessario ridurre al minimo il numero di volte in cui ogni tabella viene toccata. Come ha spiegato Brent, la correzione può comportare un codice brutto che causa il blocco delle query, ma almeno non deadlock. In questo caso, un blocco di breve durata che consente a entrambe le query di essere eseguite fino al completamento è meglio di un deadlock che ne termina una.
Nessuno vuole modificare il codice in centinaia di query, quindi concentrati su quelle che sono costantemente in deadlock, rimuovi le righe non necessarie dalla transazione e non aver paura di introdurre un blocco per evitare un deadlock.