Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Domanda SQL Deadlock

I SELECT non possono eseguire il deadlock con altri SELECT, perché acquisiscono solo blocchi condivisi. Dici che dovremmo considerare che questi SELECT ora 'richiedono blocchi di lettura esclusivi', ma questo non è possibile considerarlo perché 1) non esiste un exlusive read lock e 2) le letture non acquisiscono blocchi esclusivi.

Ma tu poni una domanda più generale, se semplici affermazioni possono bloccarsi. La risposta è un deciso e sonoro . I blocchi vengono acquisiti al momento dell'esecuzione, non analizzati in anticipo e ordinati, quindi acquisiti in un certo ordine. Sarebbe impossibile per il motore conoscere in anticipo i blocchi necessari perché dipendono dai dati effettivi su disco e per leggere i dati necessari al motore per ... bloccare i dati.

I deadlock tra istruzioni semplici (SELECt vs. UPDATE o SELECT vs. DELETE) dovuti a un diverso ordine di accesso all'indice sono abbastanza comuni e molto facili da indagare, diagnosticare e correggere. Ma nota che c'è sempre un'operazione di scrittura coinvolta, poiché le letture non possono bloccarsi a vicenda. Per questa discussione, l'aggiunta di un suggerimento UPDLOCK o XLOCK a un SELECT dovrebbe essere considerata una scrittura. Non hai nemmeno bisogno di un JOIN, un indice secondario potrebbe introdurre il problema dell'ordine di accesso che porta al deadlock, vedi Lettura/scrittura deadlock .

E infine, scrivendo SELECT FROM A JOIN B oppure scrivendo SELECT FROM B JOIN A è del tutto irrilevante. Query Optimizer è libero di riorganizzare l'ordine di accesso come meglio crede, il testo effettivo della query non impone in alcun modo l'ordine di esecuzione.

Aggiornato

Temo che non ci sia una ricetta per gli stampini. La soluzione dipenderà da caso a caso. In definitiva, nelle applicazioni di database i deadlock sono un dato di fatto. Capisco che questo possa sembrare assurdo, come in "siamo atterrati sulla Luna ma non possiamo scrivere un'applicazione di database corretta", ma ci sono forti fattori in gioco che praticamente garantiscono che le applicazioni alla fine incontreranno deadlock. Gli stalli fortunati sono il più facile gestire gli errori, semplice rileggere lo stato, applicare la logica, riscrivere il nuovo stato. Detto questo, ci sono alcune buone pratiche che possono ridurre drasticamente la frequenza dei deadlock, fino al punto in cui sono quasi svaniti:

  • Cerca di avere un modello di accesso coerente per le scritture . Avere regole chiaramente definite che affermino cose come "una transazione deve sempre essere classificata in questo ordine:Customers -> OrderHeaders -> OrderLines .' Tieni presente che l'ordine deve essere eseguito all'interno di una transazione . Fondamentalmente, classifica tutti tabelle nello schema e specifica che tutti gli aggiornamenti devono avvenire in ordine di classificazione. Questo alla fine si riduce alla disciplina del codice del singolo contributore che scrive il codice, in quanto deve assicurarsi che scriva l'aggiornamento nell'ordine corretto all'interno di una transazione.
  • Riduci la durata di scritture. La solita saggezza è questa:all'inizio della transazione fai tutte le letture (leggi lo stato esistente), quindi elabora la logica e calcola nuovi valori, quindi scrivi tutti gli aggiornamenti alla fine della transazione. Evita un modello come "lettura->scrittura->logica->lettura->scrittura", invece fai "lettura->lettura->logica->scrittura->scrittura". Certo, il vero artigianato consiste nel come affrontare casi reali, reali, individuali quando apparentemente uno deve devo fare scritture a metà transazione. Una nota speciale qui va fatta su un tipo specifico di transazione:quelle guidate da una coda, che per definizione iniziano la loro attività rimuovendo la coda (=una scrittura) dalla coda. Queste applicazioni sono sempre state notoriamente difficili da scrivere e soggette a errori (specialmente deadlock), fortunatamente ci sono modi per farlo, vedi Utilizzo delle tabelle come code .
  • Riduci la quantità di letture. Le scansioni delle tabelle sono il principale causa di stallo. Una corretta indicizzazione non solo eliminerà i deadlock, ma potrebbe anche migliorare le prestazioni nel processo.
  • Isolamento snapshot . Questa è la cosa più vicina a un pranzo gratis per evitare gli stalli. L'ho messo intenzionalmente per ultimo, perché potrebbe mascherare altri problemi (come l'indicizzazione impropria) invece di risolverli.

Cercando di risolvere questo problema con un LockCustomerByXXX approccio temo non funzioni. Il blocco pessimistico non scala. Concorrenza ottimistica gli aggiornamenti sono il strada da percorrere se vuoi avere qualsiasi tipo di prestazione decente.