web-dev-qa-db-fra.com

Deadlock MySQL InnoDB pour 2 requêtes d'insertion simples

J'ai une impasse pour ces deux requêtes d'insertion:

insert into PlayerClub (modifiedBy, timeCreated, currentClubId, endingLevelPosition, nextClubId, account_id) values (0, '2014-12-23 15:47:11.596', 180, 4, 181, 561)

insert into PlayerClub (modifiedBy, timeCreated, currentClubId, endingLevelPosition, nextClubId, account_id) values (0, '2014-12-23 15:47:11.611', 180, 4, 181, 563)

Voici le statut InnoDB:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2014-12-23 15:47:11 1f4c
*** (1) TRANSACTION:
TRANSACTION 19896526, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 1
MySQL thread id 17988, OS thread handle 0x17bc, query id 5701353 localhost 127.0.0.1 root update
insert into PlayerClub (modifiedBy, timeCreated, currentClubId, endingLevelPosition,  nextClubId, account_id) values (0, '2014-12-23 15:47:11.596', 180, 4, 181, 561)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 49735 page no 4 n bits 72 index `UK_cagoa3q409gsukj51ltiokjoh` of   table `db`.`playerclub` trx id 19896526 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

*** (2) TRANSACTION:
TRANSACTION 19896542, ACTIVE 0 sec inserting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 1
MySQL thread id 17979, OS thread handle 0x1f4c, query id 5701360 localhost 127.0.0.1    root update
insert into PlayerClub (modifiedBy, timeCreated, currentClubId, endingLevelPosition,   nextClubId, account_id) values (0, '2014-12-23 15:47:11.611', 180, 4, 181, 563)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 49735 page no 4 n bits 72 index `UK_cagoa3q409gsukj51ltiokjoh` of   table `db`.`playerclub` trx id 19896542 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 49735 page no 4 n bits 72 index `UK_cagoa3q409gsukj51ltiokjoh` of    table `db`.`playerclub` trx id 19896542 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

*** WE ROLL BACK TRANSACTION (2)

La seule clé foriegn sur cette table est la "compte_id".

Des idées?

EDIT: Voici mes informations sur la PlayerClub:

CREATE TABLE `PlayerClub` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `modifiedBy` bigint(20) DEFAULT NULL,
  `timeCreated` datetime NOT NULL,
  `account_id` bigint(20) DEFAULT NULL,
  `currentClubId` bigint(20) DEFAULT NULL,
  `endingLevelPosition` int(11) NOT NULL,
  `nextClubId` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_cagoa3q409gsukj51ltiokjoh` (`account_id`),
  KEY `FK_cagoa3q409gsukj51ltiokjoh` (`account_id`),
  CONSTRAINT `FK_cagoa3q409gsukj51ltiokjoh` FOREIGN KEY (`account_id`) REFERENCES   `PlayerAccount` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
10
Urbanleg

Voici les faits

Voici les deux inserts

insert into PlayerClub (modifiedBy, timeCreated, currentClubId, endingLevelPosition, nextClubId, account_id) values (0, '2014-12-23 15:47:11.596', 180, 4, 181, 561)
insert into PlayerClub (modifiedBy, timeCreated, currentClubId, endingLevelPosition, nextClubId, account_id) values (0, '2014-12-23 15:47:11.611', 180, 4, 181, 563)

Voici les deux lignes de votre SHOW ENGINE INNODB STATUS\G

RECORD LOCKS space id 49735 page no 4 n bits 72 index `UK_cagoa3q409gsukj51ltiokjoh` of   table `db`.`playerclub` trx id 19896526 lock_mode X insert intention waiting
RECORD LOCKS space id 49735 page no 4 n bits 72 index `UK_cagoa3q409gsukj51ltiokjoh` of   table `db`.`playerclub` trx id 19896542 lock_mode X

Observations

Vous faites un insert avec deux comptes_Diens différents: 561 et 563.

Ils sont uniques et ne devraient pas avoir de problèmes, non? TORT !!!

En raison de l'indice groupé d'InnoDB, il peut toujours y avoir une impasse. Pourquoi ?

Regardez sur vos deux inserts. Le PRIMARY KEY Sur ID in non spécifié. Il doit être généré automatiquement. Toute clé autre que la clé primaire (unique ou non unique) aura la principale clé jointe.

Veuillez noter la documentation MySQL sur la manière dont un indice secondaire et une clé primaire sont entrelacés :

Tous les index autres que l'indice en cluster sont appelés index secondaires. En InnoDB, chaque enregistrement dans un indice secondaire contient les colonnes de clé primaire de la ligne, ainsi que les colonnes spécifiées pour l'indice secondaire. InnoDB utilise cette valeur de clé principale pour rechercher la ligne de l'index en cluster.

Si la clé principale est longue, les index secondaires utilisent plus d'espace. Il est donc avantageux d'avoir une clé primaire courte.

Bien que vous insérez Compte_ID 561 et 563, sous la hotte, vous insérez 561-(id) et 563-(id) dans l'index UK_cagoa3q409gsukj51ltiokjoh. Le PRIMARY KEY Devient le goulot d'étranglement car l'index secondaire doit attendre jusqu'à ce que la colonne id est auto_générée.

RECOMMANDATION

Vous avez une table avec deux clés candidates

  • PRIMARY KEY Sur id
  • UNIQUE KEY Sur UK_cagoa3q409gsukj51ltiokjoh

Puisque les deux sont BIGINT, vous pouvez augmenter les performances et avoir une table plus petite PlayerClub en vous débarrassant de id et maintenez toujours unicité à cause de UK_cagoa3q409gsukj51ltiokjoh Ainsi que éviter cette situation d'impasse.

13
RolandoMySQLDBA