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

Problema di deadlock di MySQL con InnoDB

Questo sta causando un deadlock perché UPDATE query sta bloccando tutte le righe della tabella e, a seconda degli indici utilizzati (o della loro mancanza), due sessioni diverse le bloccheranno potenzialmente in un ordine leggermente diverso. Ricorda che UPDATE , DELETE e SELECT ... FOR UPDATE bloccherà tutte le righe che incontrano, se quelle righe corrispondono a tutti WHERE condizioni o meno. Quindi, quando li usi, dovresti sforzarti di essere sicuro che incontrino il minor numero possibile di righe, utilizzando gli indici (idealmente la chiave primaria) ed evitando condizioni vaghe o di selezione ampia.

Il mio suggerimento per le code di lavoro è praticamente universale:blocca il meno possibile il più raramente possibile e sempre in un ordine deterministico. Quindi, in genere:

  1. Utilizza letture non bloccanti (normale SELECT ) per trovare lavoro da fare cercando cose che il tuo lavoratore sa come fare e che al momento non sono reclamate (lease_owner IS NULL AND lease_expiry IS NULL -- o simili).
  2. Scegli un oggetto di lavoro (o alcuni se ne hai il coraggio, ma uno è molto più semplice e normalmente consente prestazioni perfettamente accettabili).
  3. Aggiorna il tuo oggetto di lavoro (per reclamarlo, ma in ogni caso deve essere aggiornato anche lui):
    1. Apri una transazione.
    2. Blocca l'elemento di lavoro scelto con SELECT ... FOR UPDATE -- Se non è più non reclamato, abortisci e scegline un altro.
    3. Aggiorna l'elemento di lavoro scelto con il tuo ID lavoratore e un tempo di scadenza per il tuo contratto di locazione su di esso.
    4. Compila immediatamente la tua transazione.
  4. Inizia a lavorare sui tuoi oggetti di lavoro noleggiati.
  5. In qualche altro processo, un altro poller cerca il lavoro abbandonato e non lo rivendica (attraverso lo stesso processo di aggiornamento sopra).

È possibile ottenere facilmente un throughput molto elevato con questo design (migliaia di lavori al secondo) e sostanzialmente senza contese e senza problemi di ordinazione. Le ottimizzazioni per scegliere il lavoro che ha meno probabilità di entrare in conflitto con altri sondaggi sono semplici ed efficaci (ad es. modulo su Job ID o simili, scelto per evitare la fame di lavoro). La chiave è ricordare che il conflitto sulla selezione del lavoro è ok -- interrompi e riprova e tutto procede molto rapidamente.

Tutte le scritture di blocco per gli elementi/lavori della coda di lavoro devono essere eseguite solo su singole righe e per chiave primaria solo .