ホームページ  >  記事  >  データベース  >  Mysql update SQL によって引き起こされる本番環境のエラーを解決する方法

Mysql update SQL によって引き起こされる本番環境のエラーを解決する方法

WBOY
WBOY転載
2023-05-31 13:31:141063ブラウズ

障害の兆候

  • 一方で、: Alibaba Cloud コンソールのクラウド データベース PolarDB に対応するクラスター管理ページで、診断および最適化モジュール 診断セッションの管理中に、特定の更新 SQL の実行時間が非常に長く、非常に頻繁であることが判明しました。

  • ##一方、##注※:業務監視システムに業務実行時間が継続的に表示されるようになりました アラーム情報が発行され、アラームの業務データが増加し続け、一部の操作がお客様の利用に影響を与えるようになりました。

  • ビジネスの背景

ビジネス運営に関わるビジネス フローは比較的複雑であるため、純粋に技術的な観点からは、焦点を絞った議論ではありません。この問題が起こった理由は、この複雑なビジネスを次のように例えて説明することです: データベースには 3 つのテーブルがあり、最初のテーブルは

t_grandfather

(祖父のテーブル) で、2 番目のテーブルは t_grandfather (祖父のテーブル) です。テーブルは t_father (親テーブル)、3 番目のテーブル t_grandson (子孫テーブル)、DDL は次のとおりです:

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='孙子表';

3 つのテーブル間のビジネス ロジック関係つまり、まず孫テーブルを作成し、次にこの男性は多くの妻 (ビジネス) を娶り、子供を産み続けます。子供が生まれると、父親のテーブルが生成されます。同時に、そのカウント = count 1 が生成されます。男性のテーブルが更新され、新しい子孫が追加されたことがわかります。男性の妻(ビジネス))赤ちゃんが生まれ続けると、先に生まれた赤ちゃんにも妻が生まれ、その妻も赤ちゃんを産みます。マスターの場合は、孫がいることを意味します (新しいビジネス データを生成する) 孫ができたら、マスター テーブルの count=count 1 も更新する必要があります。これは、新しい子孫が追加されたことを意味します。次の図に示すように、子孫は無限に存在します (ビジネス データは継続的に生成されます)。

Mysql update SQL によって引き起こされる本番環境のエラーを解決する方法

祖先コードのロジックは、新しい追加がある限り次のとおりです。 t_father テーブルに追加すると、t_grandsont_grandfather が更新されます。この論理設計は大きな問題ではありませんが、孫テーブルに大量のデータがあることを考慮すると、ここで非常に深刻なパフォーマンスの問題が発生します。以下は、ビジネス

 /**
 * 处理 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());
     }
}

から抽出された疑似コードの一部です。複数のビジネス (スレッド) がそれぞれ上記のメソッドを呼び出すと、t_grandfather テーブルの更新操作に大きな負荷がかかります。 , 特に同じ ID を更新する場合、MySQL サーバー内のロックの競争は非常に熾烈になります。最終的なパフォーマンスは、上記の背景説明と一致しています。

解決策

1. 一時的な解決策:

一方で、Alibaba Cloud コンソールで SQL のフローを制限し、通常はブロックします。データスレッドがブロックされないようにセッションを強制終了してリソースを解放する一方、リクエストを受け取るサービスのノード数を減らすことで業務データの入力量を削減することを目的としています。

2 . 長期的な解決策

一方で、上記のビジネス ロジックを変更し、t_grandson テーブルと t_father テーブルを挿入するときに、 t_grandfather テーブルは更新されなくなります。一方、カウント統計要件が必要な場合は、すべて他のメソッドに切り替えます。

以上がMysql update SQL によって引き起こされる本番環境のエラーを解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。