Deadlock MySQL InnoDB Untuk 2 permintaan insert sederhana

10

Saya memiliki jalan buntu untuk dua kueri sisipan ini:

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)

Berikut adalah status 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)

Satu-satunya kunci asing pada tabel ini adalah "account_id".

Ada ide?

EDIT: Ini adalah info PlayerClub saya:

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
sumber
Apa lagi yang Anda lakukan dalam setiap transaksi sebelum menemui jalan buntu?
Michael - sqlbot
bagaimana jika Anda mengeluarkan komit setelah setiap sisipan dan kemudian coba? Beri tahu kami ..
Nawaz Sohail
SHOW CREATE TABLE PlayerClubsilahkan. Ini biasanya terkait dengan indeks.
Jehad Keriaki

Jawaban:

13

DI SINI ADALAH FAKTA

Inilah dua 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)

Berikut adalah dua baris dari Anda 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

PENGAMATAN

Anda melakukan INSERT dengan dua akun_id yang berbeda: 561 dan 563.

Mereka unik dan seharusnya tidak memiliki masalah, bukan? Salah !!!

Karena InnoDB's Clustered Index, masih ada jalan buntu. Mengapa

Lihat kembali kedua INSERT Anda. Nomor PRIMARY KEYid tidak ditentukan. Itu harus dibuat secara otomatis. Kunci apa pun selain KUNCI UTAMA (unik atau non-unik) akan memiliki KUNCI UTAMA.

Harap perhatikan Dokumentasi MySQL tentang bagaimana Indeks Sekunder dan Kunci Utama saling terkait :

Semua indeks selain indeks berkerumun dikenal sebagai indeks sekunder. Di InnoDB, setiap catatan dalam indeks sekunder berisi kolom kunci utama untuk baris, serta kolom yang ditentukan untuk indeks sekunder. InnoDB menggunakan nilai kunci utama ini untuk mencari baris dalam indeks berkerumun.

Jika kunci primer panjang, indeks sekunder menggunakan lebih banyak ruang, sehingga menguntungkan untuk memiliki kunci primer pendek.

Meskipun Anda memasukkan akun_id 561 dan 563, di bawah tenda Anda memasukkan 561-(id)dan 563-(id)ke dalam UK_cagoa3q409gsukj51ltiokjohindeks. Itu PRIMARY KEYmenjadi hambatan karena Indeks Sekunder harus menunggu sampai idkolom otomatis dihasilkan.

REKOMENDASI

Anda memiliki meja dengan dua kunci kandidat

  • PRIMARY KEY di id
  • UNIQUE KEY di UK_cagoa3q409gsukj51ltiokjoh

Karena keduanya adalah BIGINT, Anda dapat meningkatkan kinerja dan memiliki PlayerClubmeja yang lebih kecil dengan menyingkirkan iddan masih mempertahankan keunikan karena UK_cagoa3q409gsukj51ltiokjohjuga menghindari situasi kebuntuan ini.

RolandoMySQLDBA
sumber
1
Hanya setelah menghapus Kunci foriegn hanya pada tabel ini adalah "account_id" kebuntuan berhenti terjadi.
Urbanleg