MySQL InnoDB Deadlock для 2 простых запросов вставки

10

У меня есть тупик для этих двух запросов вставки:

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)

Вот статус 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)

Единственным внешним ключом в этой таблице является "account_id".

Любые идеи?

РЕДАКТИРОВАТЬ: Вот моя информация 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
Urbanleg
источник
Что еще вы делали в каждой транзакции, прежде чем попасть в тупик?
Майкл - sqlbot
Что делать, если вы выполните коммит после каждой вставки, а затем попробуйте? Дайте нам знать ..
Наваз Сохаил
SHOW CREATE TABLE PlayerClubПожалуйста. Это обычно связано с индексами.
Джехад Кериаки

Ответы:

13

ЗДЕСЬ ФАКТЫ

Вот две вставки

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)

Вот две строки из вашего 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

НАБЛЮДЕНИЯ

Вы делаете INSERT с двумя разными account_ids: 561 и 563.

Они уникальны и не должны иметь проблем, верно? НЕПРАВИЛЬНО !!!

Из-за кластерного индекса InnoDB все еще может быть тупик. Почему ?

Оглянись на свои два ВСТАВКИ. PRIMARY KEYНа идентификатор в не указано. Это должно быть автоматически сгенерировано. К любому ключу, кроме PRIMARY KEY (уникальному или неуникальному), будет присоединен PRIMARY KEY.

Обратите внимание на документацию MySQL о том, как переплетаются вторичный индекс и первичный ключ :

Все индексы, кроме кластеризованного, называются вторичными. В InnoDB каждая запись во вторичном индексе содержит столбцы первичного ключа для строки, а также столбцы, указанные для вторичного индекса. InnoDB использует это значение первичного ключа для поиска строки в кластерном индексе.

Если первичный ключ длинный, вторичные индексы используют больше места, поэтому выгодно иметь короткий первичный ключ.

Хотя вы вставляете account_id 561 и 563, под капотом вы вставляете 561-(id)и 563-(id)в UK_cagoa3q409gsukj51ltiokjohиндекс. PRIMARY KEYСтановится узким местом , так как Secondary Index должен ждать , пока idколонна не auto_generated.

РЕКОМЕНДАЦИЯ

У вас есть таблица с двумя ключами-кандидатами

  • PRIMARY KEY на id
  • UNIQUE KEY на UK_cagoa3q409gsukj51ltiokjoh

Поскольку и то, и другое BIGINTможно повысить производительность и получить меньшую PlayerClubтаблицу, избавившись idи сохранив уникальность благодаря UK_cagoa3q409gsukj51ltiokjohизбежанию этой тупиковой ситуации.

RolandoMySQLDBA
источник
1
Только после удаления. Единственным ключом foriegn в этой таблице является "account_id", когда происходит взаимоблокировка.
Urbanleg