Analyse et solutions au blocage de la base de données causé par la fusion d'index MySQL | Équipe technique JD Cloud

arrière-plan

Dans DBS-Cluster List-More-Connection Query-Deadlock, j'ai vu un journal de blocage de base de données le 22 septembre. Après enquête, j'ai découvert que le blocage de la base de données était causé par la fusion de l'index d'optimisation MySQL.

définition

Fusion d'index : une technologie d'optimisation des requêtes de base de données, introduite après MySQL 5.1. Elle peut interroger plusieurs index et fusionner les résultats.

Mécanisme de verrouillage de la base de données MySQL

Avant de résoudre le problème, parlez d'abord du mécanisme de verrouillage de la base de données mysql :

1 L'unité de base du verrouillage est le verrouillage à clé suivante (verrouillage d'enregistrement + verrouillage d'espace). Lorsque le verrouillage d'enregistrement ou le verrouillage d'espace peut résoudre le problème de la lecture fantôme, il dégénère en verrouillage d'enregistrement (verrouillage de ligne) et verrouillage d'espace.

2 Le verrouillage ajoute des verrous à l'index, pas aux données.

3 Pour la lecture en cours, l'index est verrouillé. L'instruction de lecture en cours comprend (select... from. ... pour la mise à jour, select... from ..... verrouiller en mode partage, mettre à jour..., supprimer ...).

4. Le verrouillage se distingue par un index unique et un index non unique. Selon les conditions de requête, il est divisé en requêtes de valeur égale et requêtes de plage. Selon que les données peuvent être trouvées, elles sont divisées en existence d'enregistrement et non existence.

L'index utilisé dans ce problème de blocage est l'existence d'enregistrements dans la requête équivalente de l'index non unique, donc cet article ne présente cette situation qu'en détail. Pour d'autres situations, vous pouvez consulter le document de référence 1 en bas :

La situation de verrouillage est la suivante : il analysera en séquence. Tout d'abord, il analysera les données qui correspondent à la condition et ajoutera un verrou à clé suivante. Ensuite, il analysera le premier enregistrement qui ne correspond pas aux données, ajoutera un verrou d'espacement, et enfin trouver la clé primaire de l'enregistrement.Ajouter un verrou d'enregistrement,

Trois types de verrous ont été ajoutés pour la situation ci-dessus. Le but du verrouillage est d'empêcher les lectures fantômes de se produire.

Analysez les verrous sur les index secondaires :

Structure du tableau :

CREATE TABLE `jdi_roster_apply_detail` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `apply_id` varchar(100) NOT NULL COMMENT '申请单号',
  `status` tinyint(10) NOT NULL COMMENT '状态',
  PRIMARY KEY (`id`),
  KEY `idx_status` (`status`),
  KEY `idx_apply_id` (`apply_id`)
) ENGINE=InnoDB AUTO_INCREMENT=984483 DEFAULT CHARSET=utf8 COMMENT='黑白名单申请单明细'

Données du tableau :

identifiant appliquer_id statut
959651 1695369220522068998 1
960738 1695369227576173690 1
961319 1695373047673903326 1
961365 16953731224447865228 1

Arbre b+ établi via idx_apply_id :

L'index étant un index secondaire, les données stockées dans les nœuds feuilles constituent la valeur de clé primaire.

Exécutez SQL :

select * from jdi_roster_apply_detail where apply_id='1695369227576173690' for update

Effectuer le processus d'analyse des données

1 Recherchez l'enregistrement qui remplit les conditions et ajoutez le verrou à clé suivante, de sorte que le verrou soit (1695369220522068998,1695369227576173690]

2 Recherchez les premières données qui ne correspondent pas à l'enregistrement et augmentez le verrouillage de l'espace, de sorte que le verrouillage soit (1695369227576173690, 1695373047673903326)

3 Ajoutez un verrou d'enregistrement à l'index de clé primaire qui remplit les conditions, ajoutez donc un verrou d'enregistrement à id=960738.

Lecture fantôme pour trois types de solutions de verrouillage :

1 S'il n'y a pas de verrou de clé suivante pour le premier élément et qu'une autre transaction ajoute apply_id=1695369227576173690 et id<960738, la transaction aura un enregistrement supplémentaire lors de l'interrogation, provoquant ainsi une lecture fantôme.

2 S'il n'y a pas de deuxième verrou d'espacement et qu'une autre transaction ajoute apply_id=1695369227576173690, id>960738, la transaction aura un enregistrement supplémentaire lors de l'interrogation, provoquant ainsi une lecture fantôme.

3. S'il n'y a pas de troisième verrouillage d'enregistrement et qu'une autre transaction supprime un enregistrement avec l'identifiant = 960738, il y aura une donnée de moins lors de l'interrogation de la transaction, provoquant ainsi une lecture fantôme.

Analyse de problèmes pratiques

Journal des blocages de base de données

Les deux transactions du journal ci-dessus ont exécuté respectivement des instructions de mise à jour :

#事务1
update jdi_roster_apply_detail set `status` = 10 where `status` = 1 and apply_id = '1695369220522068998'
#事务2
update jdi_roster_apply_detail set `status` = 10 where `status` = 1 and apply_id = '1695369227576173690' 

Ce SQL est utilisé pour modifier les données en attente d'approbation d'un certain ID d'application en approuvées.

Étant donné que l'instruction update ne peut pas être exécutée dans Taishan, l'instruction select est exécutée pour vérifier l'état de l'index :

explain select * from  jdi_roster_apply_detail  where `status` = 1 and apply_id = '1695369220522068998'

Résultat de l'exécution :

Les résultats montrent que les deux instructions de mise à jour utilisent deux index, à savoir idx_status et idx_apply_id. Les résultats trouvés sont ensuite fusionnés, de sorte que pendant le processus de simulation, ils peuvent être divisés en deux instructions de requête.

Simulation de blocage

Opération 1 Opération 2 plage de verrouillage
commencer commencer  
sélectionnez * dans jdi_roster_apply_detail où apply_id = '1695369220522068998' pour la mise à jour   idx_apply_id est verrouillé (-∞, 1695369220522068998], (1695369220522068998, 1695369227576173690) L'index d'identification de clé primaire est verrouillé id=959651
  sélectionnez * dans jdi_roster_apply_detail où apply_id = '1695369227576173690' pour la mise à jour idx_apply_id est verrouillé (1695369220522068998, 1695369227576173690], (1695369227576173690, 1695373047673903326) L'index d'identification de clé primaire est verrouillé id=960738
sélectionnez * dans jdi_roster_apply_detail où status = 1 pour la mise à jour   Les verrous de clé suivante et les verrous d'espacement seront ajoutés à idx_status, mais lorsque des verrous d'enregistrement sont ajoutés aux clés primaires 959651, 960738, 961319 et 961365, la transaction 2 a déjà ajouté des verrous d'enregistrement à 960738, donc la transaction 1 est bloquée.
  sélectionnez * dans jdi_roster_apply_detail où status = 1 pour la mise à jour Les verrous de clé suivante et les verrous d'espacement seront ajoutés à idx_status, mais lorsque des verrous d'enregistrement sont ajoutés aux clés primaires 959651, 960738, 961319 et 961365, la transaction 1 a déjà ajouté des verrous d'enregistrement à 959651, donc la transaction 2 est bloquée.
  impasse  

Deux transactions nécessitent chacune des verrous d'enregistrement pour deux ID de clé primaire, ce qui se fait attendre et forme une impasse.

Ce qui précède consiste à exécuter d'abord la requête d'index de idx_apply_id, puis la requête d'index de idx_status. Si la requête d'index de idx_status est exécutée en premier, puis la requête d'index de idx_apply_id, un blocage sera également provoqué en raison du verrouillage d'enregistrement du principal. clé.

solution

1 Utilisez force index(idx_apply_id) pour forcer un index afin qu'InnoDB ignore la fusion d'index et évite que plusieurs index ne soient verrouillés en même temps.

2 Désactivez la fusion d'index. Utilisez la commande pour désactiver la fusion d'index : SET GLOBAL optimiseur_switch='index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off';

3 Index Merge utilise deux index indépendants en même temps, créez donc un nouvel index conjoint contenant tous les champs de ces deux index, afin qu'InnoDB n'utilise que cet index conjoint séparé.

La troisième solution a de meilleures performances de requête que la première. Par rapport à la deuxième solution, elle n'affecte que la table et a une portée d'impact plus petite. Par conséquent, cette solution est également adoptée cette fois.

Résumer

Le problème de blocage était dû à l'utilisation par l'optimiseur d'un index fusionné, qui a finalement été résolu en créant un nouvel index commun.

Documentation de référence :

1 https://www.xiaolincoding.com/mysql/lock/how_to_lock.html

Auteur : JD Industriel Li Xiaohui

Source : Communauté de développeurs JD Cloud Veuillez indiquer la source lors de la réimpression

L'auteur du framework open source NanUI s'est tourné vers la vente d'acier et le projet a été suspendu. La liste gratuite numéro un dans l'App Store d'Apple est le logiciel pornographique TypeScript. Il vient de devenir populaire, pourquoi les grands commencent-ils à l'abandonner ? Liste TIOBE d'octobre : Java connaît la plus forte baisse, C# se rapproche de Java Rust 1.73.0 publié Un homme a été encouragé par sa petite amie IA à assassiner la reine d'Angleterre et a été condamné à neuf ans de prison Qt 6.6 officiellement publié Reuters : RISC-V la technologie devient la clé de la guerre technologique sino-américaine Nouveau champ de bataille RISC-V : non contrôlé par une seule entreprise ou un seul pays, Lenovo prévoit de lancer un PC Android
{{o.name}}
{{m.nom}}

Je suppose que tu aimes

Origine my.oschina.net/u/4090830/blog/10117355
conseillé
Classement