Mysql
 sql >> Database >  >> RDS >> Mysql

Come evitare MySQL 'Deadlock trovato durante il tentativo di ottenere il blocco; prova a riavviare la transazione'

Un semplice trucco che può aiutare con la maggior parte dei deadlock è ordinare le operazioni in un ordine specifico.

Ottieni un deadlock quando due transazioni tentano di bloccare due blocchi su ordini opposti, ad esempio:

  • connessione 1:blocca la chiave(1), blocca la chiave(2);
  • connessione 2:blocca la chiave(2), blocca la chiave(1);

Se entrambi vengono eseguiti contemporaneamente, la connessione 1 bloccherà la chiave(1), la connessione 2 bloccherà la chiave(2) e ogni connessione attenderà che l'altra rilasci la chiave -> deadlock.

Ora, se hai modificato le tue query in modo tale che le connessioni bloccherebbero le chiavi nello stesso ordine, ad esempio:

  • connessione 1:blocca la chiave(1), blocca la chiave(2);
  • connessione 2:blocca la chiave(1 ), blocca la chiave(2 );

sarà impossibile ottenere un deadlock.

Quindi questo è quello che suggerisco:

  1. Assicurati di non avere altre query che bloccano l'accesso a più di una chiave alla volta, ad eccezione dell'istruzione delete. se lo fai (e sospetto che tu lo faccia), ordina il loro WHERE in (k1,k2,..kn) in ordine crescente.

  2. Correggi la tua dichiarazione di eliminazione in modo che funzioni in ordine crescente:

Cambia

DELETE FROM onlineusers 
WHERE datetime <= now() - INTERVAL 900 SECOND

A

DELETE FROM onlineusers 
WHERE id IN (
    SELECT id FROM onlineusers
    WHERE datetime <= now() - INTERVAL 900 SECOND 
    ORDER BY id
) u;

Un'altra cosa da tenere a mente è che la documentazione MySQL suggerisce che in caso di deadlock il client dovrebbe riprovare automaticamente. puoi aggiungere questa logica al tuo codice client. (diciamo, 3 tentativi su questo particolare errore prima di arrendersi).