大きな MySQL テーブルに列を追加する方法

大きな MySQL テーブルに列を追加する方法

質問は https://www.zhihu.com/question/440231149 から参照されています。MySQL では、テーブルに 3 億のデータがあり、テーブルに分割されていません。この大きなテーブルにデータの列を追加する必要があります。データベースを停止することはできず、追加、削除、変更の操作がまだ残っています。どうすればいいですか?答えはオリジナルです

MySQL の古いバージョンでは、列を追加するために次の操作を行っていました。

ALTER TABLE テーブルに COLUMN 新しい列 char(128); を追加します。

テーブルロックが発生します。簡単なプロセスは次のとおりです。

  • Table1と完全に同型の新しいTable2を作成します。
  • Table1に書き込みロックを追加する
  • ALTER TABLE 你的表ADD COLUMN 新列char(128)
  • Table1のデータをTable2にコピーする
  • Table2の名前をTable1に変更し、Table1を削除して、関連するすべてのロックを解除します。

データ量が非常に多い場合、テーブルロック時間が非常に長くなり、その間はすべてのテーブル更新がブロックされ、オンラインビジネスを正常に実行できなくなります。

MySQL 5.6 より前のバージョン (含まれません)では、トリガーを使用して、あるテーブルへの更新を別のテーブルに繰り返し、データを同期します。データの同期が完了すると、ビジネスはテーブル名を新しいテーブルに変更して公開します。営業停止はございません。トリガーの設定は次のようになります。

各行の元のテーブルに更新後にトリガー person_trigger_update を作成します。 
begin set @x = "トリガーUPDATE";
新しいテーブルに置き換えます。SELECT * from original table where new table.id = original table.id;
終了の場合;
終わり;

MySQL 5.6 以降のバージョンでは、オンライン DDL 機能が導入されています。

テーブルを変更します。ALGORITHM [=] {DEFAULT|INSTANT|INPLACE|COPY}、LOCK [=] {DEFAULT| NONE| SHARED| EXCLUSIVE }

パラメータは次のとおりです。

アルゴリズム:

  • DEFAULT : デフォルト モード。MySQL 8.0 では、ALGORITHM が指定されていない場合、最初に INSTANT アルゴリズムが選択されます。これが失敗した場合は、INPLACE アルゴリズムが使用されます。INPLACE アルゴリズムがサポートされていない場合は、COPY メソッドが使用されます。
  • INSTANT : 8.0 で追加された新しいアルゴリズム。追加された列はすぐに返されます。ただし、仮想列にすることはできません。原理は非常に単純です。新しい列が作成されても、テーブル内の元のデータはすべてすぐに変更されるわけではありません。列とデフォルト値のみがテーブル ディクショナリに記録されます。デフォルトの動的行形式 (実際には圧縮のバリアント) の場合、列が更新されると、元のデータは削除済みとしてマークされ、更新されたレコードが最後に追加されます。そうすると、事前にキュー スペースが予約されていないことになり、その後の更新によって行レコード スペースが変更される可能性が高くなります。しかし、ほとんどの企業では最新の記録のみが変更されるため、大きな問題にはなりません。
  • INPLACE : 一時テーブルをコピーせずに元のテーブルを直接変更します。大量の undolog と redolog を生成したり、多くのバッファを占有したりすることなく、レコードを 1 つずつ変更します。これにより、テーブルの再構築によって発生する IO と CPU の消費を回避でき、期間中の良好なパフォーマンスと同時実行性が保証されます。
  • COPY : 変更のために一時的な新しいテーブルにコピーします。レコードのコピーにより、大量のundologとredologが生成され、多くのバッファが占有されるため、業務パフォーマンスに影響を及ぼします。

ロック:

  • DEFAULT : ALGORITHMのDEFAULTと同様
  • NONE : ロックなし、テーブルの同時読み取りと更新が可能
  • SHARED : 共有ロック。読み取りは許可するが更新は許可しない。
  • 排他的: 読み取りと更新は許可されていません

さまざまなバージョンでサポートされているオンライン DDL 変更アルゴリズムの比較:

画像

参考資料:

MySQL 5.6: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.htmlMySQL

5.7: https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.htmlMySQL

8.0: https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html

これは次の方法で実行できます。

テーブルにALTER TABLEを実行し、新しい列 char(128)、ALGORITHM=INSTANT、LOCK=NONE を追加します。

同様のステートメントは、オンラインでフィールドを追加する場合にも使用されます。 DDL を実行する際に、オンライン業務にどの程度の影響を与えるかを明確に把握できるように、 ALGORITHM と LOCK を指定するのが最適です。

同時に、オンライン DDL を実行するプロセスは、おおよそ次のようになります。

画像

初期段階ではメタデータ ロックが必要であることがわかります。メタデータ ロックは MySQL 5.5 で導入されました。以前にもメタデータを保護するための同様のメカニズムはありましたが、メタデータ ロックの概念は明確に提案されていませんでした。ただし、メタデータ保護に関しては、5.5 より前のバージョン (5.1 など) と 5.5 以降のバージョンの間には大きな違いがあります。5.1 はステートメント レベルでメタデータを保護しますが、5.5 はトランザクション レベルでメタデータを保護します。いわゆるステートメント レベルとは、ステートメントが実行された後、トランザクションがコミットされたかロールバックされたかに関係なく、他のセッションによってテーブル構造を更新できることを意味します。一方、トランザクション レベルとは、トランザクションが終了した後にのみメタデータ ロックが解除されることを意味します。

メタデータ ロックの導入により、主に 2 つの問題が解決されます。1 つはトランザクション分離の問題です。たとえば、反復可能分離レベルでは、セッション A が 2 つのクエリ中にテーブル構造を変更すると、2 つのクエリ結果に矛盾が生じ、反復可能読み取りの要件を満たすことができません。もう 1 つはデータ複製の問題です。たとえば、セッション A が複数の更新ステートメントを実行し、別のセッション B がテーブル構造を変更して最初にコミットすると、スレーブは最初に変更をやり直し、次に更新をやり直すため、複製エラーが発生します。

現在実行中のトランザクションが多数あり、次のような大きなクエリを含むトランザクションがある場合:

トランザクションを開始します。
テーブルからcount(*)を選択します

これにより、トランザクションの実行に長い時間がかかり、ブロックされることになります。

したがって、原則として、

  • 大規模な取引を避ける
  • 営業時間外にテーブル構造を変更する

大規模な MySQL テーブルに列を追加する方法についての記事はこれで終わりです。大規模な MySQL テーブルに列を追加する方法の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Innodb で MySQL の 2T テーブルをすばやく削除する方法の例
  • 大規模な MySQL テーブル内の繰り返しフィールドに対する高効率クエリ方法
  • 大きなテーブルを削除する際の MySQL パフォーマンス問題の解決策
  • 数千万のデータを含む MySQL テーブルを最適化するにはどうすればよいでしょうか?
  • クラウドデータ移行サービスの観点から見たMySQLの大規模テーブル抽出モードの原理分析

<<:  JavaScript の静的スコープと動的スコープを例を使って説明します

>>:  CSS でのナビゲーション バーとドロップダウン メニューの実装

推薦する

Unix/Linuxフォークの隠れたオーバーヘッド

目次1. フォークの起源2. 初期のUNIXオーバーレイ技術3. UNIXに導入される前のフォークの...

docker windows10共有ディレクトリのマウント失敗の解決策

原因docker スクリプトを実行すると、コンテナを作成できないというエラーが発生します。以下のよう...

HTMLのimgタグで画像の中心部分だけを表示する方法(3つの方法)

HTML の img タグで画像の中心を表示する方法は、現在 3 つあります。ここで記録しておきま...

axios を使用してプロジェクト内の複数の繰り返しリクエストをフィルタリングする方法

目次1. はじめに:この場合、通常は 2 つのアプローチがあります。 2. CancelToken ...

VMware Workstationはデバイス/資格情報ガードと互換性がありません

仮想マシンをインストールするときに、「VMware ワークステーションはデバイス/資格情報ガードと互...

Vue.$set の失敗の落とし穴の発見と解決

偶然、プロジェクト内でVue.$setが無効であることがわかりましたデータ フィルタリングを追加する...

Navicat を仮想マシン MySQL に接続する際によくあるエラーと解決策

質問1 解決するサービスを開始します: service mysqld start; /sbin/ip...

JSは要素のドラッグとプレースホルダー機能を実装します

このブログ投稿は、ブロガーが数日前に取り組んだプロジェクトで遭遇した困難についてです。これを学んだ後...

Tudou.comのホームページのデザイン方法

<br />私は数年間フロントエンドに取り組んできました。フロントエンドについて完全に理...

JS関数の継承について学ぶ記事

目次1. はじめに: 2. プロトタイプチェーン継承: 3. コンストラクタ継承の借用(オブジェクト...

Linux コマンドラインでパケットをキャプチャするために tcpdump を使用するいくつかの機能

tcpdump は、ネットワークの問題のトラブルシューティングに効果的に役立つ、柔軟で強力なパケット...

MySQL のデフォルトのストレージ エンジンを変更する方法

mysql ストレージ エンジン: MySQL サーバーはモジュール スタイルを採用しており、特にス...

Linux でユーザー アカウントをロックおよびロック解除する 3 つの方法

組織内で何らかのパスワード ポリシーがすでに実装されている場合は、この記事を読む必要はありません。た...

MySQL ビューの原則分析

目次更新可能なビュービューのパフォーマンスビューの制限ビューは MySQL 5.0 以降で導入されま...

MySQLクエリ最適化: 100万件のデータに対するテーブル最適化ソリューション

1. 2つのクエリエンジン(myIsamエンジン)のクエリ速度InnoDB はテーブル内の特定の行数...