MySQL InnoDB Deadlock for 2つの単純な挿入クエリ


10

この2つの挿入クエリにはデッドロックがあります。

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)

このテーブルの唯一のforiegnキーは「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

デッドロックに陥る前に、各トランザクションで他に何をしましたか?
マイケル-sqlbot 2014

挿入するたびにcommitを発行してから試行するとどうなりますか?私たちは知ってみましょう...
ナワズSohail

SHOW CREATE TABLE PlayerClubお願いします。これは通常、インデックスに関連しています。
Jehad Keriaki 14

回答:


13

ここに事実があります

ここに2つのINSERTがあります

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)

ここにあなたの2行があります 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

観測

561と563の2つの異なるaccount_idでINSERTを実行しています。

彼らはユニークで問題はないはずですよね?違う !!!

InnoDBのクラスター化インデックスが原因で、デッドロックが発生する可能性があります。どうして ?

2つのINSERTを振り返ってください。PRIMARY KEY指定されていないのidに。自動生成する必要があります。PRIMARY KEY以外のキー(一意または非一意)には、PRIMARY KEYがアタッチされます。

セカンダリインデックスとプライマリキーの関係についてはMySQLのドキュメントに注意してください。

クラスタ化インデックス以外のすべてのインデックスは、セカンダリインデックスと呼ばれます。InnoDBでは、セカンダリインデックスの各レコードには、行のプライマリキー列と、セカンダリインデックスに指定された列が含まれます。InnoDBはこの主キー値を使用して、クラスター化インデックス内の行を検索します。

主キーが長い場合、セカンダリインデックスはより多くのスペースを使用するので、主キーを短くすることが有利です。

account_id 561と563を挿入していますが、内部ではインデックスに挿入561-(id)563-(id)ていUK_cagoa3q409gsukj51ltiokjohます。PRIMARY KEYセカンダリインデックスがするまで待たなければならないため、ボトルネックとなりid、列がauto_generatedされます。

勧告

2つの候補キーを持つテーブルがあります

  • PRIMARY KEY オン id
  • UNIQUE KEY オン UK_cagoa3q409gsukj51ltiokjoh

両方ともなので、このデッドロックの状況を回避するだけでなく、一意性を排除して維持することでBIGINT、パフォーマンスを向上させ、PlayerClubテーブルを小さくすることができます。idUK_cagoa3q409gsukj51ltiokjoh


1
削除後のみこのテーブルの唯一のforiegnキーは、デッドロックが発生しなくなった「account_id」です。
Urbanleg 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.