sql >> Databasteknik >  >> RDS >> Mysql

Oväntad låsning för bord med primärnyckel och unik nyckel

Problemet du upplever beror på att MySQL inte bara låser tabellraden för ett värde du ska infoga, det låser alla möjliga värden mellan föregående id och nästa id i ordning, så återanvänd ditt exempel nedan:

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);

Anta att du börjar med transaktion TX1:

START TRANSACTION;
REPLACE INTO foo VALUES(8,8);

Sedan om du startar en transaktion TX2 , oavsett INSERT eller REPLACE med ett id mellan 5 och 11 kommer att låsas:

START TRANSACTION;
REPLACE INTO foo VALUES(11,11);

Det verkar som att MySQL använder den här typen av låsning för att undvika "fantomproblemet" som beskrivs här:http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL använder en "nästa-nyckellåsning", som kombinerar indexradslåsning med gaplåsning, detta betyder för oss att den kommer att låsa många möjliga id mellan föregående och nästa id, och även låsa föregående och nästa id .

För att undvika detta försök skapa en serveralgoritm som infogar dina poster så att poster som infogas i olika transaktioner inte överlappar, eller åtminstone inte kör alla dina transaktioner samtidigt så att TX behöver inte vänta på varandra.



  1. Definiera sammansatt nyckel med automatisk ökning i MySQL

  2. SQL Server-kodsidor och sorteringar

  3. Hur man aktiverar den långsamma frågeloggen i MySQL

  4. Hur går man med i ResultSet-objekt i java?