10
votes

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

J'ai rencontré un problème de verrouillage InnoDB pour les transactions sur une table avec une clé primaire et un indice unique séparé. Il semble si un TX supprime une enregistrement à l'aide d'une clé unique, puis réinsère ce même enregistrement, cela se traduira par un verrou de clé suivant au lieu de la serrure d'enregistrement prévue (puisque la clé est unique). Voir ci-dessous pour un étui à tester ainsi que la ventilation des enregistrements que je m'attends à avoir ce que serrures: xxx pré>

(Remarque: il suffit d'exécuter le TX2 SQL après la connexion TX1 SQL, dans une connexion distincte)

TX1 H2>
START TRANSACTION; 
INSERT INTO foo VALUES(7,7); 


0 commentaires

3 Réponses :


7
votes

Le problème que vous rencontrez se produit car MySQL ne verrouille pas simplement la ligne de table pour une valeur que vous allez insérer, il verrouille toutes les valeurs possibles entre le précédent ID code> et l'identifiant suivant ordre, donc, réutilisez votre exemple ci-dessous:

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


1 commentaires

Non, MySQL n'émet pas de verrouillages de l'écart pour les insertions d'index groupées (il émet un verrou d'intention d'intention d'insertion qui ne bloque pas d'insertions simultanées dans l'écart). Cela semble être lié à la suppression de la suppression et de l'insertion ultérieure à un indice groupé et non clusterné (marquage de suppression avec une suppression ultérieure) qui a abouti à une double écluse (qui est ce que vous avez remarqué), mais cela semble inutile tome.



4
votes

Il semble que le problème puisse mentir dans le fait que les indices InnoDB sont bizarres.

La clé principale (clustered) est i et il y aurait un Rowid associé à celui-ci.

La clé unique sur j (non clustered) a le rowid de i associé à la valeur de j dans l'index.

faire un Supprimer suivi d'un insert sur la même valeur de clé pour i devrait produire un autre Rowid Pour la clé primaire (clustered) et, également, un autre Rowid à associer à la valeur de j (non clustered).

Cela nécessiterait du verrouillage interne bizarre au sein du mécanisme MVCC.

Vous devrez peut-être modifier le niveau d'isolation de votre transaction pour permettre des lectures sales (c'est-à-dire de ne pas avoir de lecture répétable)

jouer des jeux avec tx_isolation variable dans une session
Essayez read_committed et read_uncommited

Cliquez ici pour voir la syntaxe pour la définition du niveau d'isolation dans un Session
Cliquez ici pour voir comment il y avait une fois un bogue concernant cela dans une session et l'avertissement sur la manière dont Pour l'utiliser soigneusement

Sinon, il suffit de définir la permanente dans /etc/my.cnf (exemple)

[mysqld]
transaction_isolation = lecture-engagée

Essayez !!!


0 commentaires

0
votes

https://bugs.mysql.com/bug.php?id=68021

Ce problème de bogue répond à votre question.

Il s'agit de la faille de conception de Innodb, l'amont utilisé pour fixer ce problème pour éviter le verrouillage de l'écart dans Row_ins_Scan_sec_index_for_duplicate dans l'isolation en lecture. Cependant, il ressort un autre problème, la cause du correctif cause une violation clé unique de l'indice secondaire silencieusement, de sorte que l'amont revenait ce correctif.


0 commentaires