MySQL InnoDB Deadlock Para 2 consultas simples de inserção

10

Eu tenho um impasse para essas duas consultas de inserção:

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)

Aqui está o status do 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)

A única chave obrigatória nesta tabela é o "account_id".

Alguma ideia?

EDIT: Aqui estão as informações do meu 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
fonte
O que mais você fez em cada transação antes de atingir o impasse?
Michael - sqlbot
e se você emitir commit após cada inserção e tentar? Deixe-nos saber ..
Nawaz Sohail
SHOW CREATE TABLE PlayerClubpor favor. Isso geralmente está relacionado aos índices.
Jehad Keriaki

Respostas:

13

AQUI ESTÃO OS FATOS

Aqui estão os dois 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)

Aqui estão as duas linhas do seu 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

OBSERVAÇÕES

Você está executando um INSERT com dois account_ids diferentes: 561 e 563.

Eles são únicos e não devem ter problemas, certo? ERRADO !!!

Devido ao índice clusterizado do InnoDB, ainda pode haver um impasse. Por quê ?

Olhe para seus dois INSERTs. O PRIMARY KEYon-in não especificado. Ele deve ser gerado automaticamente. Qualquer chave que não seja a PRIMARY KEY (exclusiva ou não exclusiva) terá a PRIMARY KEY anexada.

Observe a documentação do MySQL sobre como um índice secundário e uma chave primária são entrelaçados :

Todos os índices diferentes do índice clusterizado são conhecidos como índices secundários. No InnoDB, cada registro em um índice secundário contém as colunas da chave primária da linha, bem como as colunas especificadas para o índice secundário. O InnoDB usa esse valor de chave primária para procurar a linha no índice em cluster.

Se a chave primária for longa, os índices secundários usarão mais espaço, portanto, é vantajoso ter uma chave primária curta.

Embora você esteja inserindo account_id 561 e 563, sob o capô você está inserindo 561-(id)e 563-(id)no UK_cagoa3q409gsukj51ltiokjohíndice. O PRIMARY KEYse torna o gargalo porque o índice secundário tem que esperar até que a idcoluna é auto_generated.

RECOMENDAÇÃO

Você tem uma tabela com duas chaves candidatas

  • PRIMARY KEY em id
  • UNIQUE KEY em UK_cagoa3q409gsukj51ltiokjoh

Como os dois são BIGINT, você pode aumentar o desempenho e ter uma PlayerClubtabela menor se livrando ide ainda manter a exclusividade UK_cagoa3q409gsukj51ltiokjoh, além de evitar essa situação de conflito.

RolandoMySQLDBA
fonte
11
Somente após a remoção A única chave obrigatória nesta tabela é o "account_id" que o conflito para de ocorrer.
precisa saber é o seguinte