2015-09-10 16 views
5

Ho un'applicazione multithread che prova a INSERT un record in una tabella in più batch. Ogni thread che processa un batch. A volte ottengo l'errore Deadlock, che segue è la traccia.Deadlock in MySQL a causa dell'inserimento di più thread

La tabella che sto cercando di inserire un record in è come questo:

RecordBase (Col1, Col2, Col3)

Col1 e Col2 insieme formano una chiave primaria composta.

Prima pensavo che potesse essere dovuto a un blocco index-record ma la traccia mostra chiaramente che le istruzioni che si bloccano a vicenda non hanno record duplicati. Allora perché sta causando stallo?

------------------------ LATEST DETECTED DEADLOCK ------------------------ 
2015-09-09 17:13:22 2b70324de700 

*** (1) TRANSACTION: 
TRANSACTION 1787379600, ACTIVE 7 sec inserting mysql tables in use 1, locked 1 LOCK WAIT 486 lock struct(s), heap size 63016, 13085 row lock(s), undo log entries 8713 MySQL thread id 537443, OS thread handle 0x2b703286c700, query id 578560605 127.0.0.1 192.168.1.195 demoreleaseroot update 
INSERT INTO Record_Base VALUES 
('da5fd95c-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5fcf08-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5fc4eb-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5fbabe-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5fb087-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5fa616-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5f99bf-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5f8f0f-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5f5e2e-4d8e-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('da5f52e3-4d8e-11e5-9761-22000bd9028a','101e7d 

*** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 26232190 page no 5961 n bits 160 index `PRIMARY` of table `provalant101_mxradon`.`Record_Base` trx id 1787379600 lock_mode X locks gap before rec insert intention waiting Record lock, heap no 29 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 30; hex 65376566306364332d353039352d313165352d393736312d323230303062; asc e7ef0cd3-5095-11e5-9761-22000b; (total 36 bytes); 1: len 30; hex 31303165376463642d346338312d313165352d396361302d323230303062; asc 101e7dcd-4c81-11e5-9ca0-22000b; (total 36 bytes); 2: len 6; hex 00006a893f90; asc j ? ;; 3: len 7; hex b40001a7c3290f; asc  ) ;; 4: len 4; hex 80000000; asc  ;; *** 

(2) TRANSACTION: TRANSACTION 1787379848, ACTIVE 1 sec inserting mysql tables in use 1, locked 1 1030 lock struct(s), heap size 112168, 5801 row lock(s), undo log entries 2639 MySQL thread id 537467, OS thread handle 0x2b70324de700, query id 578563042 127.0.0.1 192.168.1.195 demoreleaseroot update INSERT INTO Record_Base VALUES 
('4849f98e-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('4849ebe5-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('4849c44c-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('4849add7-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('4849a0ef-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('48499430-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('48498752-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('48496d2d-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('4848731e-5094-11e5-9761-22000bd9028a','101e7dcd-4c81-11e5-9ca0-22000bd8028c','0'), 
('4846784e-5094-11e5-9761-22000bd9028a','101e7d 

*** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 26232190 page no 5961 n bits 152 index `PRIMARY` of table `provalant101_mxradon`.`Record_Base` trx id 1787379848 lock_mode X locks gap before rec Record lock, heap no 29 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 30; hex 65376566306364332d353039352d313165352d393736312d323230303062; asc e7ef0cd3-5095-11e5-9761-22000b; (total 36 bytes); 1: len 30; hex 31303165376463642d346338312d313165352d396361302d323230303062; asc 101e7dcd-4c81-11e5-9ca0-22000b; (total 36 bytes); 2: len 6; hex 00006a893f90; asc j ? ;; 3: len 7; hex b40001a7c3290f; asc  ) ;; 4: len 4; hex 80000000; asc  ;; 

*** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 26232190 page no 14639 n bits 192 index `PRIMARY` of table `provalant101_mxradon`.`Record_Base` trx id 1787379848 lock_mode X locks gap before rec insert intention waiting Record lock, heap no 121 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 30; hex 38393531613333352d353039342d313165352d393736312d323230303062; asc 8951a335-5094-11e5-9761-22000b; (total 36 bytes); 1: len 30; hex 31303165376463642d346338312d313165352d396361302d323230303062; asc 101e7dcd-4c81-11e5-9ca0-22000b; (total 36 bytes); 2: len 6; hex 00006a893f90; asc j ? ;; 3: len 7; hex b40001a7c71c1c; asc  ;; 4: len 4; hex 80000000; asc  ;; 

*** WE ROLL BACK TRANSACTION (2) 
+1

I deadlock si verificano quando più transazioni contengono richieste di blocco. Nel tuo caso, hai più thread che colpiscono la stessa tabella, quindi è previsto che si verifichi il deadlock. Un deadlock non è motivo per allarmarsi. InnoDB li rileva automaticamente e genera errori. Per noi, sviluppatori che usano MySQL, ciò significa che dobbiamo solo ripetere la query in caso di errore. In alcuni pseudo-codice, sarebbe qualcosa di simile a 'while (true) if (do_query()) break; ' – Mjh

+0

@Mjh Ho fatto lo stesso per far funzionare la mia applicazione. Vorrei solo sapere in dettaglio che cosa sta causando questo stallo. – Aashish

+0

Il deadlock è causato dai thread che accedono contemporaneamente alla stessa tabella (accesso simultaneo). Per evitare di sovrascrivere i dati, MySQL consente l'accesso sequenziale alla tabella, per scrivere. Affinché un thread o un processo possa scrivere su una tabella, deve acquisire un blocco.Tuttavia, quando due thread stanno combattendo per acquisire un lock - nessuno lo acquisirà mai - che mette in un loop infinito. Per uscire da questo ciclo, MySQL lancia degli errori e chiama questo "deadlock". TL; DR: il tuo inserto simultaneo da più thread a una tabella sta causando deadlock. (questa è una spiegazione semplificata) – Mjh

risposta

7

Questi tipi di deadlock sono noti come Gap Locks. Ho trovato questo post abbastanza utile.

Inoltre, è possibile leggere di più su Gap blocco nella Mysql Manual

+1

Oltre a ciò che viene detto nel post collegato, è possibile avere un deadlock sugli inserimenti simultanei senza un vincolo di chiave univoco, solo avere una combinazione di chiave primaria generata automaticamente e un altro indice può portare al problema. Vedi https://dba.stackexchange.com/questions/86878/mysql-innodb-deadlock-for-2-simple-insert-queries –

1

Deadlock successo molto nella mia applicazione in passato a causa di meccanismi di MySQL. L'ho risolto in due modi. Innanzitutto, inserisco i lavori batch che interessano la stessa tabella nello stesso thread e li eseguo in sequenza, in secondo luogo metto un blocco try-catch attorno alle esecuzioni delle query per rilevare l'errore deadlock e lasciare che proverà la stessa esecuzione di query 5+ volte inclusa una funzione sleep tra i tentativi .

0

Ho ricevuto questo stesso problema, la risposta di @Aashish me lo ha spiegato, quindi se vuoi capire perché questo ha funzionato per me devi leggere la sua risposta.

Lo scenario che ho avuto:

Ho avuto un indice univoco su colonne Data e idSomething (L'ordine è importante, data di 1 ° e idSomething secondo)

ho avuto un pool di 12 thread inserimento lo stesso intervallo di date (3 giorni) per ogni idSomething (circa 1500 differenti idSomethings).

La correzione:

Cambiare l'indice univoco di essere sulla colonna di idSomething (1 °) e la data (2 °). Quindi il processo invece di elaborare "Somethings" in modo ordinato, ho aggiunto un shuffle all'ordine, quindi sarebbe meno probabile che idSomething I e I + 1 verrebbero raggruppati contemporaneamente. In questo modo i Gap Locks non si sono sovrapposti e le deadlock sono scomparse.

+0

Puoi elaborare, non capire la correzione –