Het probleem dat u ondervindt, gebeurt omdat MySQL niet alleen de tabelrij vergrendelt voor een waarde die u gaat invoegen, het vergrendelt alle mogelijke waarden tussen de vorige id
en de volgende id in volgorde, dus hergebruik je voorbeeld hieronder:
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);
Stel dat u begint met transactie TX1:
START TRANSACTION;
REPLACE INTO foo VALUES(8,8);
Als u vervolgens een transactie start TX2
, wat dan ook INSERT
of REPLACE
met een id
tussen 5 en 11 worden vergrendeld:
START TRANSACTION;
REPLACE INTO foo VALUES(11,11);
Het lijkt erop dat MySQL dit soort vergrendeling gebruikt om het hier beschreven "fantoomprobleem" te vermijden:http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL gebruikt een "volgende-sleutelvergrendeling", die indexrijvergrendeling combineert met gap-vergrendeling, dit betekent voor ons dat het veel mogelijke id's tussen de vorige en volgende id's vergrendelt, en ook vorige en volgende id's vergrendelt .
Om dit te voorkomen, probeert u een serveralgoritme te maken dat uw records invoegt, zodat records die in verschillende transacties zijn ingevoegd, elkaar niet overlappen, of in ieder geval niet al uw transacties tegelijkertijd uitvoeren, zodat de TX
hoeven niet op elkaar te wachten.