sql >> Database >  >> RDS >> Mysql

Onverwachte vergrendeling voor tafel met primaire sleutel en unieke sleutel

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.



  1. Aanhalingstekens negeren bij het importeren van een CSV-bestand in PostgreSQL?

  2. SQL Group By met een Order By

  3. Oracle prestatie- en afstemmingsquiz

  4. Het herstelmodel van een database in SQL Server ophalen met T-SQL