2012-07-04 15 views
10

Sto cercando di capire un deadlock trovato da MySQL durante l'elaborazione di client concorrenti sulle stesse tabelle. Questa è la parte interessante del comando "show InnoDB STATUS":Cercando di capire il deadlock di MySQL sulla tabella InnoDB

------------------------ 
LATEST DETECTED DEADLOCK 
------------------------ 
120704 16:17:51 
*** (1) TRANSACTION: 
TRANSACTION 0 3547576, ACTIVE 0 sec, process no 10886, OS thread id 140547111458560 inserting 
mysql tables in use 1, locked 1 
LOCK WAIT 2 lock struct(s), heap size 368, 1 row lock(s), undo log entries 1 
MySQL thread id 41941, query id 1725666 localhost testsuite update 
insert into `INode` (`status`,`_type`,`group`,`ctime`,`parent`,`shared`,`basename`,`_rowid`,`displayname`,`user`,`content_type`,`mtime`,`position`,`atime`,`size`) values ('Published','Group','12','2012-07-04 16:17:48.996869','2',null,'1','12','1','3','application/x-empty','2012-07-04 16:17:48.996896','1','2012-07-04 16:17:48.996914',null) 
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547576 lock mode S waiting 
Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 80000002; asc  ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc  ;; 

*** (2) TRANSACTION: 
TRANSACTION 0 3547575, ACTIVE 0 sec, process no 10886, OS thread id 140547107845888 inserting, thread declared inside InnoDB 493 
mysql tables in use 1, locked 1 
13 lock struct(s), heap size 3024, 17 row lock(s), undo log entries 21 
MySQL thread id 41940, query id 1725808 localhost testsuite update 
replace into `INode` (`status`,`_type`,`position`,`group`,`ctime`,`parent`,`basename`,`_rowid`,`displayname`,`user`,`content_type`,`mtime`,`shared`,`atime`,`size`) values ('Published','Group','0','2','2012-07-04 16:17:49','1','groups','2','admin','3','application/x-empty','2012-07-04 16:17:49',null,'2012-07-04 16:17:49',null),('Published','Group','1','11','2012-07-04 16:17:51.064074','2','1','11','1','3','inode/directory','2012-07-04 16:17:51.064074',null,'2012-07-04 16:17:51.064074',null) 
*** (2) HOLDS THE LOCK(S): 
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547575 lock_mode X locks rec but not gap 
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 
0: len 4; hex 80000001; asc  ;; 1: len 6; hex 67726f757073; asc groups;; 2: len 4; hex 80000002; asc  ;; 

Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 80000002; asc  ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc  ;; 

*** (2) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547575 lock_mode X waiting 
Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 80000002; asc  ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc  ;; 

*** WE ROLL BACK TRANSACTION (1) 

Quello che ho capito da questo registro è che l'operazione (1) è in attesa di ottenere un blocco condiviso sull'indice INodeparent_basename del tavolo testsuite. INode. Ora, la transazione (2) ha un blocco esclusivo su questo stesso stesso indice. Ma ciò che è strano è che la transazione (2) sta anche aspettando un blocco X su una data tabella. Perché? Se la transazione (2) ha già il blocco, perché lo aspetta?

(in generale, non ho trovato alcuna documentazione che spiega esattamente come leggere l'output del comando stato - sarebbe interessante se qualcuno potesse farlo notare anche a me)

+0

Hai trovato una risposta a questo? Ho lo stesso problema. –

+0

No, non sono riuscito a trovare una risposta a questo problema. Dopo aver provato per alcune ore a comprenderlo, ho dovuto codificare i processi in modo diverso e serializzare a livello di codice una parte degli accessi ai database per evitare possibili situazioni di deadlock rilevate da MySQL. Le prestazioni sono probabilmente peggiori, ma non avevo altre possibilità. – RedGlow

+0

Informazioni su come tradurre l'output del comando di stato, tu (o qualsiasi altra persona che ha bisogno di aiuto su questo) potresti voler controllare questo blog che ho trovato https://www.percona.com/blog/2014/10/28/how- to-deal-with-mysql-deadlocks/ – CodeBurner

risposta

1

In questo caso, transazione 2 acquisito un blocco condiviso per un'istruzione precedente. (* (2) contiene il blocco (S) :)

Poi, transazione 1 tentato di acquisire un blocco esclusivo sulla stessa riga, ed è in attesa del blocco condiviso da rimuovere.

Quindi, la transazione 2, in un'altra istruzione, ha tentato di acquisire un blocco esclusivo sulla stessa riga. Deadlock verificato.

+0

No, (2) possiede già un blocco esclusivo. (1) sta cercando di ottenere un blocco condiviso tu. –

-1

Non so se sarà di aiuto o meno, ma una cosa da considerare è la sequenza di operazioni che causano il blocco. Sembra che in un solo luogo della app che si sta creando le serrature come

Tabella 1 Tabella 2

e in un altro a fare

tabella 2 Tabella 1 (solo esempio)

Senza vedendo il codice effettivo, suggerisco di guardare a cose come questa e assicurandoti di farle nella stessa sequenza di lavoro/aggiornamento/inserimento dei record in modo che funzionino sempre come

inserire/aggiornare dalla tabella 1 quindi inserire/aggiornare la tabella 2

In questo modo, il primo blocco viene sempre tentato sulla tabella 1 per primo .. se ciò non può andare, quindi non viene nemmeno tentata la tabella 2 fino alla tabella 1 è stato rilasciato.

Quindi, applicare qualsiasi modifica alla tabella 2 e completare la transazione. Quando vengono rilasciate entrambe le tabelle 2 e 1, la transazione successiva in attesa di rilascio sulla tabella 1 può quindi procedere.

Problemi correlati