Maison  >  Article  >  base de données  >  Comment résoudre les échecs de production causés par la mise à jour MySQL

Comment résoudre les échecs de production causés par la mise à jour MySQL

WBOY
WBOYavant
2023-05-31 13:31:141101parcourir

Manifestations de défauts

  • D'une part : Sur la page de gestion du cluster correspondant à la base de données cloud PolarDB dans la console Alibaba Cloud, dans la gestion des sessions de diagnostic en un clic dans le module de diagnostic et d'optimisation, il a été constaté que une certaine mise à jour SQL a pris beaucoup de temps à s'exécuter. Et très fréquemment ;

  • D'un autre côté : Le système de surveillance de l'entreprise a commencé à émettre en continu des invites d'informations d'alarme pendant le temps d'exécution de l'entreprise, ainsi que les données commerciales de l'alarme. a continué d'augmenter et certaines opérations ont affecté l'utilisation des clients.

Contexte commercial

Étant donné que le flux commercial impliqué dans les opérations commerciales est relativement complexe, si le partage de technologie pure n'est pas au centre de la discussion, afin d'être plus propice à la compréhension des raisons de l'apparition du problème , des analogies sont utilisées pour diviser le complexe. L'analogie métier est la suivante : il y a trois tables dans la base de données, la première table est t_grandfather (table grand-père), la deuxième table est t_father (table parent), la troisième table est t_grandson (table descendante), DDL Comme suit :

CREATE TABLE `t_grandfather ` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `count` int(11) NOT NULL DEFAULT 0 COMMENT '子孙后代数量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爷表';

CREATE TABLE `t_father ` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `grandfather_id` int(11) NOT NULL COMMENT '老爷表id',
  PRIMARY KEY (`id`),
  KEY `idx_grandfather_id` (`grandfather_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爸表';

CREATE TABLE `t_grandson` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `grandfather_id` int(11) NOT NULL COMMENT '老爷表id',
  PRIMARY KEY (`id`),
  KEY `idx_grandfather_id` (`grandfather_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='孙子表';

La relation logique métier entre les trois tables est que d'abord la table principale est générée, puis le maître prend plusieurs femmes (entreprise) et continuera à avoir des bébés . Lorsqu'un bébé est né, une table papa sera générée en même temps. Le count=count+1 de la table du maître sera mis à jour, indiquant qu'une nouvelle progéniture a été ajoutée lorsque la femme (l'entreprise) du maître continue. avoir des bébés, les bébés nés avant auront également des femmes, et leurs femmes auront également des bébés. Pour le maître, cela signifie qu'il a un petit-fils (générant de nouvelles données commerciales, il doit également mettre à jour le). count=count+1 de la table du maître, ce qui signifie qu'un nouveau descendant a été ajouté, et ainsi de suite. Il n'y a pas de descendants exhaustifs (les données métiers sont générées en continu) Comme le montre la figure ci-dessous : La logique de

Comment résoudre les échecs de production causés par la mise à jour MySQL.

le code ancestral est que tant qu'il y a de nouveaux ajouts à la table t_father et t_grandson, mettez à jour t_grandfather. Cette conception logique n'est pas un gros problème, mais compte tenu de la grande quantité de données dans la table des petits-enfants, un problème de performances très sérieux se posera ici. Ce qui suit fait partie du pseudo code extrait de l'entreprise

 /**
 * 处理 father 的业务
 */
 public void doFatherBusiness  (){
     //do fatherBusiness baba .... 此处省
     // 插入 t_father 表
    if (fatherMapper.inster(father)){
         //update t_grandfather set count=count+1 where id= #{grandfatherId}
         grandfatherMapper.updateCount(father.getGrandfatherId  ())  ;
     }
}


 /**
 * 处理 grandson 的业务
 */
 public void doGrandsonBusiness  (){
     //do grandson baba .... 此处省略
     // 插入 t_grandson 表
     if(grandsonMapper.inster(grandson)){
          //update t_grandfather set count=count+1 where id= #{grandfatherId}
          grandfatherMapper.updateCount(grandson.getGrandfatherId());
     }
}

Lorsque plusieurs entreprises (threads) appellent respectivement la méthode ci-dessus, cela entraînera une pression énorme sur l'opération de mise à jour de la table t_grandfather, en particulier lorsque le même identifiant est mis à jour. La concurrence pour les verrous au sein du serveur MySQL est très féroce. La performance finale est conforme à la description de fond ci-dessus.

Solution

1. Solution temporaire :

D'une part, dans la console Alibaba Cloud, limiter le flux de SQL, et forcer la suppression de la session normalement bloquée afin que le thread de données ne soit pas bloqué et libéré des ressources, d'autre part, réduire le nombre de nœuds pour le service qui reçoit les requêtes, dans le but de réduire la quantité de données commerciales saisies

2 Solution à long terme

D'une part, modifier l'activité ci-dessus ; logique et insérez la table t_grandson et la table t_father, ne mettez plus à jour le champ de comptage de la table t_grandfather, par contre, lorsque les exigences statistiques de comptage sont nécessaires, toutes sont basculées vers d'autres méthodes ;

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer