Mysql
 sql >> Database >  >> RDS >> Mysql

Blocco imprevisto per tavolo con chiave primaria e chiave univoca

Il problema che stai riscontrando si verifica perché MySQL non si limita a bloccare la riga della tabella per un valore che stai per inserire, ma blocca tutti i valori possibili tra il precedente id e il prossimo id in ordine, quindi, riutilizzando il tuo esempio qui sotto:

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

Supponiamo di iniziare con la transazione TX1:

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

Quindi se avvii una transazione TX2 , qualunque INSERT o REPLACE utilizzando un id tra le 5 e le 11 sarà bloccato:

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

Sembra che MySQL utilizzi questo tipo di blocco per evitare il "problema fantasma" descritto qui:http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL utilizza un "blocco della chiave successiva", che combina il blocco della riga dell'indice con il blocco del gap, questo significa per noi che bloccherà molti possibili ID tra l'ID precedente e successivo e bloccherà anche gli ID precedente e successivo .

Per evitare ciò prova a creare un algoritmo del server che inserisca i tuoi record in modo che i record inseriti in transazioni diverse non si sovrappongano, o almeno non esegua tutte le tue transazioni contemporaneamente in modo che il TX non devono aspettarsi l'un l'altro.