MySQL移行計画と落とし穴の実践記録

MySQL移行計画と落とし穴の実践記録

背景

過去のビジネス データは MySQL に保存されるため、操作記録テーブル video_log があります。ユーザーがレコードを作成、更新、または監査人がレコードを確認するたびに、対応する video_log にログが追加されます。このログ テーブルには挿入のみがあります。ご想像のとおり、1 つのビデオは複数のログに対応します。1 日に 100,000 本のビデオがある場合、1 つのビデオに対して平均 5 つのログは、1 日に 500,000 ログ、1 か月に 50 * 30 = 1,500 万レコード、1 年に 1500 * 12 = 1 億 8,000 万レコードを意味します。現在、オンライン上のデータは 2 億件以上あります。ログ自体は C エンド向けではなく、問題を照会するために使用されるため、若干の遅延は許容されます。 しかし、時間が経つにつれて、どうしても速度が遅くなり、効率に影響が出るため、変換のアイデアが提案されました。

解決策1: 古いデータをバックアップする

ログ自体は最も重要なデータではありませんが、高いリアルタイム性能も要求されるため(リアルタイムクエリの問題)、コアとなる基本ストレージは変更せずに、古いデータを移行するというアイデアが当初の考えでした。結局のところ、1年前の操作記録を突然クエリする可能性は非常に低いです。突然確認する必要がある場合は、オフラインにすることができます。設計面では、毎日午前 4 時頃 (ビジネスのオフピーク時間帯) にデータを抽出するスケジュールされたスクリプトのみが必要です。抽出されたデータは、何らかのオフライン ストレージ (一般的に企業には Hive ベースのデータ ウェアハウスなどがある) にレポートできるため、オンラインの video_log データは増加し続けます。

オプション2: テーブルを分割する

テーブルを分割することも解決策の 1 つです。ソリューション 1 と比較すると、すべてのデータをリアルタイムでクエリできるという利点があります。欠点は、コードを変更する必要があることです。

  • まず、シャーディング キーを確認します。video_log はビデオにバインドされているため、シャーディング キーとして video_id を当然選択します。
  • テーブルの分割方法が決まったので、テーブルをいくつに分割するかを確認する必要があります。まずは小さな目標を設定し、それを 3 年間続けましょう。各テーブル内の最大データ量は 1 億です (クエリが単純なため)。上記の統計によると、3 年間でおよそ 3*1.8=5 億 4000 万となり、およそ 5.4/1≈6 個のテーブルが必要になります。

次のステップは、コードを変換し、新しいデータと古いデータの読み取りと書き込みの問題を解決することです。

  • 新しいデータは新しいテーブルに直接挿入されます
  • ログ テーブルには挿入操作のみがあり、更新操作や削除操作はないため、これらのシナリオを考慮する必要はありません。
  • テーブルを分割すると、ビデオのログが 2 つのテーブル (古いテーブルと新しいテーブル) に存在するため、両方のテーブルを一時的にチェックしてから結合します。
  • 古いデータを新しいテーブルに同期する
  • 古いテーブルを読み取るためのオフラインコード

解決策3: tidbに移行する

オプション 2 の欠点は明らかです。3 年後はどうすればよいのでしょうか? メーターの解体を続けるのでしょうか?そこには常に歴史的な負債があるように感じます。そこで私たちは、分散データベースである tidb に目を向けました。tidb に接続すれば、テーブルのシャーディングについて心配する必要はありません。tidb がこれらすべてを実行し、ノードの容量を自動的に拡張します。分散されているため、tidb の主キーは順序付けられておらず、これは非常に重要です。
全体のプロセスは、おおまかに次の 4 つのステップに分けられます。

  1. 最初に二重書き込みを行う (二重書き込みの開始時に MySQL ID を記録します。この ID の前のデータは古いデータである必要があります)
  2. 古いデータを同期する(最初のステップで記録したIDで区別)
  3. カット読み取り(旧データ同期完了)
  4. 二重書き込み

古いデータを同期する際の落とし穴に焦点を当ててみましょう。

tidb への移行は簡単に思えますが、実際にはジョブ スクリプトにいくつかの落とし穴が隠れています。

  • ジョブが途中で中断され、再開しなければならない場合の対処方法も考慮する必要があります。データの再実行にかかる時間コストの他に、再実行時に同期済みのデータが重複してしまうため、重複データの問題も考慮する必要があります。重複データの問題を解決するには、古いテーブルに新しいフィールドを追加して、同期されたかどうかを示します。同期が完了するたびに、フィールドを更新します。デメリット: オンライン データが大きいため、フィールドを追加すると安全ではなく、オンラインの混雑が発生する可能性があります。
  • フィールドを追加するのは得策ではないので、既存の主キー ID を制約として使用し、主キー ID を同期します。この方法では、スクリプトを再起動して最初から実行した場合でも、同じ主キーが挿入されているため、エラーが報告され、スキップされます。完璧に思えますが、tidb は分散されており、主キー ID は連続していないため、このような状況が発生する可能性があります。通常の業務データを tidb に挿入する場合、tidb が割り当てた主キー ID と、mysql と同期した主キー ID が重複します。この場合、誰が挿入しても、最後の 1 つは必ず失敗します。

最終同期スクリプトソリューション

データの重複、ジョブの再開の効率、全体の同期の効率を考慮して、大まかに次のような計画を立てました。

  1. タスクをバッチに分割して効率化: まず、処理能力と完了予定時間に応じて、古いデータをバッチに分割します。バッチは約 10 個あります。10 個のジョブは互いに干渉することなく異なるバッチのデータを実行し、そのたびに 100 項目がバッチで更新されます。
  2. 状態を記録し、再起動後にブレークポイントに自動で復元: 各データ同期後に現在の同期位置を記録します (redis は現在の ID を記録します)。再起動しても、前回の更新位置を redis から取得して更新できます。
  3. 主キーの競合を避ける: 主キー以外のすべてのフィールドを同期します (主キーは同期しません)

最終的に、ソリューション 3 の 4 つの切り替え手順 + 効率的な同期スクリプトにより、データ移行がスムーズに完了しました。

要約する

これで、MySQL 移行ソリューションと落とし穴に関するこの記事は終了です。より関連性の高い MySQL 移行ソリューションと落とし穴については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQLデータベースのデータフォルダを移行するための詳細な手順
  • MySQLデータベースを別のマシンに移行する方法の詳細な説明
  • OracleデータベースをMySQLに移行する方法の概要
  • MySQLデータベースをOracleデータベースに移行する
  • MySQLデータベース移行により、大量のデータを迅速にエクスポートおよびインポートできます
  • MySQL InnoDB テーブルスペースのアンロード、移行、ロードの使用方法
  • MySQLデータ移行の詳しい説明 - データディレクトリ直接置換の注意事項
  • MySQLからClickHouseに移行する5つの方法
  • mysql5.5 データベースデータディレクトリ移行方法の詳細な説明
  • MySQLのバックアップと移行データの同期方法

<<:  Nginx の場所と proxy_pass パスの設定の問題の概要

>>:  シンプルで簡単なJavaScript開発のためのSvelte実装原理の詳細な説明

推薦する

一般的な Dockerfile コマンドの使用方法の紹介

目次01 CM 02 エントリーポイント03 ワークディレクトリ04 環境05 ユーザー06巻07 ...

この記事では、イベント委任を使用してJavaScriptメッセージボード機能を実装する方法について説明します。

イベント委任を使用してメッセージ ボード機能を実装します。 <!DOCTYPE html>...

Linux のスケジュールタスク Crontab コマンドの使用に関する詳細な説明と概要

crontab コマンドは、Unix および Linux で定期的な実行命令を設定するために使用され...

Docker を使用して Redis マスター スレーブ レプリケーション クラスターを構築する

マスタースレーブレプリケーションモードのクラスターでは、通常、1 つのマスターノードと 2 つ以上の...

Vueはタブルーティング切り替えコンポーネントのメソッド例を実装します

序文この記事では、vue に付属している vue-router.js ルーティングを使用してページン...

Vueモバイル端末の適応化問題の詳細説明

1. vue uiでプロジェクトを作成する 2. 基本設定項目を選択する 3. プロジェクトを実行す...

Nginxにモジュールを動的に追加する方法

前面に書かれた多くの場合、現在のプロジェクトの状況とビジネスニーズに基づいて Nginx をインスト...

Ubuntu 18.04 のログインループ/ブートインターフェイスで停止/グラフィカルインターフェイスに入ることができない問題を解決する方法

原因: NVIDIA グラフィック カード ドライバーが破損している解決:コマンドラインモードで再起...

MySQLとPythonの相互作用の例

目次1. データを準備するデータテーブルを作成するデータの挿入2. SQLドリル1. SQL文の強化...

数千万データを持つMySQLテーブルを最適化する実践記録

序文まずここで説明させてください。インターネット上では、Alibaba では 500 万のデータを異...

chkconfig および systemctl コマンドを使用して Linux サービスを有効または無効にする方法

これは Linux 管理者にとって重要な (そして素晴らしい) トピックなので、誰もが Linux ...

Baotaパネルを再起動すると、「-ModuleNotFoundError: No module named 'geventwebsocket'」というメッセージが表示されます。

背景:サーバーがFlaskプロジェクトをデプロイし、python3をインストールしたため、再起動時に...

MySQL インフラストラクチャ チュートリアル: クエリ ステートメント実行プロセスの詳細な説明

序文私は以前から、SQL 文がどのように実行され、どのような順序で実行されるのかを知りたいと思ってい...

Jenkinsを使用してプロジェクトを別のホストにデプロイするプロセス

環境ホスト名IPアドレス仕えるジェンキンス192.168.216.200トムキャット、ジェンキンスサ...

Dockerは1行のコマンドでFTPサービス構築の実装を完了します

1行のコマンド docker run -d \ -v /share:/home/vsftpd \ -...