Problém, se kterým se setkáváte, nastává proto, že MySQL nezamyká pouze řádek tabulky pro hodnotu, kterou se chystáte vložit, ale zamyká všechny možné hodnoty mezi předchozí id
a další id v pořadí, takže znovu použijte svůj příklad níže:
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);
Předpokládejme, že začnete s transakcí TX1:
START TRANSACTION;
REPLACE INTO foo VALUES(8,8);
Pak pokud zahájíte transakci TX2
, cokoliv INSERT
nebo REPLACE
pomocí id
mezi 5 a 11 bude uzamčeno:
START TRANSACTION;
REPLACE INTO foo VALUES(11,11);
Vypadá to, že MySQL používá tento druh zamykání, aby se vyhnul „fantomovému problému“ popsanému zde:http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL používá „uzamykání dalšího klíče“, které kombinuje zamykání řádků indexu se zamykáním mezer, což pro nás znamená, že zamkne mnoho možných ID mezi předchozím a dalším ID a zamkne také předchozí a další ID .
Abyste tomu zabránili, zkuste vytvořit serverový algoritmus, který vloží vaše záznamy tak, aby se záznamy vložené do různých transakcí nepřekrývaly, nebo alespoň neprováděly všechny vaše transakce ve stejnou dobu, takže TX
nemusí jeden na druhého čekat.