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:
-
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.
-
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).