Проблемът, който срещате, се случва, защото MySQL не просто заключва реда на таблицата за стойност, която ще вмъкнете, той заключва всички възможни стойности между предишния id
и следващия идентификационен номер по ред, така че повторно използване на вашия пример по-долу:
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);
Да предположим, че започвате с транзакция TX1:
START TRANSACTION;
REPLACE INTO foo VALUES(8,8);
След това, ако започнете транзакция TX2
, каквото и да е INSERT
или REPLACE
използвайки id
между 5 и 11 ще бъдат заключени:
START TRANSACTION;
REPLACE INTO foo VALUES(11,11);
Изглежда, че MySQL използва този вид заключване, за да избегне "фантомния проблем", описан тук:http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL използва „заключване на следващ ключ“, което комбинира заключване на индексни редове със заключване на празнини, това означава за нас, че ще заключи много възможни идентификатори между предишния и следващия идентификатор, както и ще заключи предишния и следващия идентификатор .
За да избегнете това, опитайте се да създадете сървърен алгоритъм, който вмъква вашите записи, така че записите, вмъкнати в различни транзакции, да не се припокриват или поне да не изпълнява всичките ви транзакции едновременно, така че TX
не е нужно да чакате един друг.