L'impasse dans MySQL due à Insérer par plusieurs threads

J'ai une application multithread qui tente de INSERT un enregistrement dans une table en plusieurs lots. Chaque thread de traitement d'un lot. À la fois, j'obtiens erreur de Blocage, à la suite de la trace.

La table, je suis en train d'essayer d'insérer un enregistrement dans est comme ceci:

RecordBase (Col1, Col2, Col3)

Col1 et Col2 ensemble la forme d'une clé primaire composite.

J'ai pensé que cela pouvait être dû à une index-enregistrement serrure, mais la trace montre clairement que les états qui bloquent les uns les autres n'ont pas de tous les enregistrements en double. Alors pourquoi est-il causer impasse?

------------------------ 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) 
Les blocages se produisent lorsque plusieurs opérations tenir les demandes d'une serrure. Dans votre cas, vous avez plusieurs threads de frapper la même table afin qu'il s'attend à ce que le blocage se produit. Un blocage n'est pas de raison de s'inquiéter. InnoDB les détecte automatiquement et jette les erreurs. Pour nous, les développeurs qui utilisent MySQL, cela signifie que nous avons juste à répéter la requête en cas d'erreur. Dans certains pseudo-code, ce serait quelque chose comme while(true) if(do_query()) break;
J'ai fait de même de faire ma demande de travail. Je voudrais juste savoir en détail ce qui est à l'origine de ce blocage.
Le blocage est causé par votre threads accèdent à la même table en même temps (l'accès simultané). Afin d'éviter d'écraser les données, MySQL permet un accès séquentiel à la table, pour écrire. Pour un thread ou processus afin d'être autorisé à écrire dans un tableau, il doit acquérir un verrou. Toutefois, lorsque deux threads se battent pour acquérir un verrou - ne sera jamais acquérir, ce qui les met dans une boucle infinie. Pour briser cette boucle, MySQL jette les erreurs et les appelle cela une "impasse". TL;DR: votre simultanées insérer à partir de plusieurs threads à une table est à l'origine des blocages. (c'est l'explication simplifiée)
Je ne pense pas que ce soit la bonne explication. Innodb a verrouillage de ligne et il n'y a rien comme l'accès séquentiel à moins que la ligne en cours d'accès est le même. Dans le cas de l'Insertion, de la dossiers sont de toute façon unique afin que les verrous de niveau ligne peuvent ne pas provoquer des blocages. J'ai fait un peu plus de recherches et découvert que ce article pour expliquer le problème parfaitement
Ok, si vous êtes bien avec une autre explication alors je ne vais pas cul. Lorsque vous écrivez, vous ne pouvez pas accéder à la table, pour écrire, en même temps que deux choses ne peuvent pas écrire à en même temps. Vous aussi vous ne pouvez pas verrouiller une ligne si il n'y a pas de ligne d'être verrouillé. Vous aussi vous ne pouvez pas calculer la auto_increment en toute sécurité, à moins que vous séquentiellement accès le compteur de placer un verrou, incrémentation, de la libération et de laisser le thread en attente d'accès. Cependant, depuis que vous avez trouvé l'explication alors je suppose que tout va bien 🙂

OriginalL'auteur Aashish | 2015-09-10