Mysql
 sql >> Base de données >  >> RDS >> Mysql

Verrouillage inattendu pour la table avec clé primaire et clé unique

Le problème que vous rencontrez se produit parce que MySQL ne se contente pas de verrouiller la ligne du tableau pour une valeur que vous allez insérer, il verrouille toutes les valeurs possibles entre le précédent id et le prochain identifiant dans l'ordre, donc, en réutilisant votre exemple ci-dessous :

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

Supposons que vous commenciez par la transaction TX1 :

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

Ensuite si vous démarrez une transaction TX2 , quel que soit INSERT ou REPLACE en utilisant un id entre 5 et 11 seront verrouillés :

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

Il semble que MySQL utilise ce type de verrouillage pour éviter le "problème fantôme" décrit ici :http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html , MySQL utilise un "verrouillage par clé suivante", qui combine le verrouillage de la ligne d'index avec le verrouillage de l'espace, cela signifie pour nous qu'il verrouillera de nombreux identifiants possibles entre les identifiants précédents et suivants, et verrouillera également les identifiants précédents et suivants .

Pour éviter cela, essayez de créer un algorithme de serveur qui insère vos enregistrements afin que les enregistrements insérés dans différentes transactions ne se chevauchent pas, ou du moins n'exécutent pas toutes vos transactions en même temps afin que le TX n'ont pas à s'attendre les uns les autres.