Masalah yang Anda alami terjadi karena MySQL tidak hanya mengunci baris tabel untuk nilai yang akan Anda masukkan, tetapi juga mengunci semua nilai yang mungkin antara id
sebelumnya dan id berikutnya secara berurutan, jadi, gunakan kembali contoh Anda di bawah ini:
DROP TABLE IF EXISTS foo;
CREATE TABLE `foo` (
`i` INT(11) NOT NULL,
`j` INT(11) DEFAULT NULL,
PRIMARY KEY (`i`),
UNIQUE KEY `jk` (`j`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
INSERT INTO foo VALUES (5,5), (8,8), (11,11);
Misalkan Anda memulai dengan transaksi TX1:
START TRANSACTION;
REPLACE INTO foo VALUES(8,8);
Kemudian jika Anda memulai transaksi TX2
, apapun INSERT
atau REPLACE
menggunakan id
antara 5 dan 11 akan dikunci:
START TRANSACTION;
REPLACE INTO foo VALUES(11,11);
Sepertinya MySQL menggunakan penguncian semacam ini untuk menghindari "masalah hantu" yang dijelaskan di sini:http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL menggunakan "penguncian tombol berikutnya", yang menggabungkan penguncian baris indeks dengan penguncian celah, ini berarti bagi kami bahwa itu akan mengunci banyak kemungkinan id antara id sebelumnya dan berikutnya, dan akan mengunci id sebelumnya dan berikutnya juga .
Untuk menghindarinya coba buat algoritme server yang menyisipkan record-record Anda agar record-record yang disisipkan pada transaksi yang berbeda tidak tumpang tindih, atau setidaknya jangan mengeksekusi semua transaksi Anda secara bersamaan agar TX
tidak harus saling menunggu.