Problem, którego doświadczasz, występuje, ponieważ MySQL nie tylko blokuje wiersz tabeli dla wartości, którą zamierzasz wstawić, ale blokuje wszystkie możliwe wartości między poprzednim id
i następny identyfikator w kolejności, więc ponownie użyj poniższego przykładu:
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);
Załóżmy, że zaczynasz od transakcji TX1:
START TRANSACTION;
REPLACE INTO foo VALUES(8,8);
Następnie, jeśli rozpoczniesz transakcję TX2
, cokolwiek INSERT
lub REPLACE
używając id
od 5 do 11 zostanie zablokowana:
START TRANSACTION;
REPLACE INTO foo VALUES(11,11);
Wygląda na to, że MySQL używa tego rodzaju blokowania, aby uniknąć opisanego tutaj „problemu fantomowego”:http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL używa "blokowania następnego klucza", które łączy blokowanie wiersza indeksu z blokowaniem odstępów, co dla nas oznacza, że zablokuje wiele możliwych identyfikatorów między poprzednim i następnym identyfikatorem, a także zablokuje identyfikatory poprzednie i następne .
Aby tego uniknąć, spróbuj stworzyć algorytm serwera, który wstawi Twoje rekordy, tak aby rekordy wstawione w różnych transakcjach nie nachodziły na siebie lub przynajmniej nie wykonywały wszystkich transakcji w tym samym czasie, więc TX
nie muszą na siebie czekać.