MySQLでのレプリケーションの設定は簡単ですが、本番環境でのレプリケーションの管理は決して簡単な作業ではありませんでした。新しいGTID自動位置決めを使用しても、何をしているのかわからない場合はうまくいかない可能性があります。レプリケーションを設定した後、あらゆる種類の問題が発生する可能性があります。間違いは簡単に発生する可能性があり、データに悲惨な結末をもたらす可能性があります。
この投稿では、MySQLレプリケーションで発生する最も一般的な間違いのいくつかと、それらを防ぐ方法について説明します。
レプリケーションの設定
MySQLレプリケーションを設定するときは、マスターからのデータセットを使用してスレーブノードをプライミングする必要があります。 Galeraクラスターのようなソリューションでは、これは選択した方法で自動的に処理されます。 MySQLレプリケーションの場合、これは自分で行う必要があるため、当然、標準のバックアップツールを使用します。
MySQLにはさまざまなバックアップツールがありますが、最も一般的に使用されるのはmysqldumpです。 Mysqldumpは、マスターのデータセットの論理バックアップを出力します。これは、データのコピーがバイナリコピーではなく、データセットを再作成するためのクエリを含む大きなファイルになることを意味します。ほとんどの場合、これによりデータの(ほぼ)同一のコピーが提供されますが、オブジェクトごとにダンプが行われるため、提供されない場合もあります。これは、データの複製を開始する前であっても、データセットがマスター上のデータセットと同じではないことを意味します。
単一のトランザクションとしてのダンプのように、mysqldumpの信頼性を高めるために実行できる調整がいくつかあります。また、ルーチンとトリガーを含めることを忘れないでください。
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > dumpfile.sql
レプリケーションの設定後にpt-table-checksumを使用して、スレーブノードが100%同じかどうかを確認することをお勧めします。
pt-table-checksum --replicate=test.checksums --ignore-databases mysql h=localhost,u=user,p=pass
このツールは、マスター上の各テーブルのチェックサムを計算し、コマンドをスレーブに複製してから、スレーブノードが同じチェックサム操作を実行します。いずれかのテーブルが同じでない場合は、チェックサムテーブルにはっきりと表示されているはずです。
間違ったレプリケーション方法の使用
MySQLのデフォルトのレプリケーション方法は、いわゆるステートメントベースのレプリケーションでした。この方法はまさにそれが何であるかです:スレーブノードで再生されるマスターで実行されるすべてのステートメントの複製ストリーム。 MySQL自体はマルチスレッドですが、(従来の)レプリケーションはそうではないため、レプリケーションストリーム内のステートメントの順序は100%同じではない可能性があります。また、ステートメントを再生すると、まったく同時に実行されない場合、異なる結果が得られる可能性があります。
これにより、データのドリフトにより、マスターとスレーブ間でデータセットが異なる可能性があります。多くの同時スレッドでMySQLを実行することはあまりなかったため、これは長年の問題ではありませんでしたが、最新のマルチCPUアーキテクチャでは、これは実際には通常の日常のワークロードで発生する可能性が高くなっています。
MySQLからの答えは、いわゆる行ベースのレプリケーションでした。行ベースのレプリケーションは可能な限りデータをレプリケートしますが、一部の例外的なケースでは引き続きステートメントを使用します。良い例は、テーブルのDLL変更です。この場合、レプリケーションは、レプリケーションを通じてテーブル内のすべての行をコピーする必要があります。これは非効率的であるため、このようなステートメントは従来の方法で複製されます。行ベースのレプリケーションがデータドリフトを検出すると、事態を悪化させることを防ぐためにスレーブスレッドを停止します。
次に、これら2つの間に方法があります。混合モードレプリケーションです。このタイプのレプリケーションは、クエリにUUID()関数、トリガー、ストアドプロシージャ、UDF、およびその他のいくつかの例外が使用されている場合を除いて、常にステートメントをレプリケートします。混合モードではデータドリフトの問題は解決されないため、ステートメントベースのレプリケーションと一緒に使用することは避けてください。
循環レプリケーション
マルチデータセンター環境を使用している場合は、マルチマスターでMySQLレプリケーションを実行する必要があります。アプリケーションは他のデータセンターのマスターが書き込みを確認するのを待つことができないため、ローカルマスターが推奨されます。通常、自動インクリメントオフセットは、マスター間のデータの衝突を防ぐために使用されます。この方法で2人のマスターに相互に書き込みを実行させることは、広く受け入れられているソリューションです。
MySQLマスター-マスターレプリケーションただし、複数のデータセンターを同じデータベースに書き込む必要がある場合は、複数のマスターが相互にデータを書き込む必要があります。 MySQL 5.7.6より前は、メッシュタイプのレプリケーションを実行する方法がなかったため、代わりに循環リングレプリケーションを使用することもできました。
MySQLリングレプリケーショントポロジMySQLでのリングレプリケーションは、遅延、高可用性、データドリフトなどの理由で問題があります。サーバーAにデータを書き込むと、サーバーDに到達するまでに3ホップかかります(サーバーBおよびC経由)。 (従来の)MySQLレプリケーションはシングルスレッドであるため、レプリケーションで長時間実行されるクエリはリング全体を停止させる可能性があります。また、いずれかのサーバーがダウンした場合、リングが壊れ、現在、リング構造を修復できるフェイルオーバーソフトウェアはありません。次に、データがサーバーAに書き込まれ、サーバーCまたはDで同時に変更されると、データドリフトが発生する可能性があります。
壊れたリングの複製一般に、循環レプリケーションはMySQLにうまく適合しないため、絶対に避ける必要があります。 Galeraは、それを念頭に置いて設計されているため、マルチデータセンターの書き込みに適した代替手段になります。
大規模な更新によるレプリケーションの停止
多くの場合、さまざまなハウスキーピングバッチジョブは、古いデータのクリーンアップから別のソースから取得された「いいね」の平均の計算に至るまで、さまざまなタスクを実行します。これは、設定された間隔で、ジョブが多くのデータベースアクティビティを作成し、ほとんどの場合、データベースに多くのデータを書き戻すことを意味します。当然、これはレプリケーションストリーム内のアクティビティが等しく増加することを意味します。
ステートメントベースのレプリケーションは、バッチジョブで使用される正確なクエリをレプリケートするため、クエリがマスターで処理されるのに30分かかった場合、スレーブスレッドは少なくとも同じ時間ストールします。これは、他のデータが複製できず、スレーブノードがマスターより遅れ始めることを意味します。これがフェールオーバーツールまたはプロキシのしきい値を超えると、クラスター内の使用可能なノードからこれらのスレーブノードが削除される可能性があります。ステートメントベースのレプリケーションを使用している場合は、ジョブのデータを小さなバッチで処理することで、これを防ぐことができます。
これで、行ベースのレプリケーションはクエリの代わりに行情報をレプリケートするため、これによる影響を受けないと思うかもしれません。これは部分的に当てはまります。DDLの変更に関しては、レプリケーションはステートメントベースの形式に戻ります。また、多数のCRUD操作がレプリケーションストリームに影響を与えます。ほとんどの場合、これは依然としてシングルスレッド操作であるため、すべてのトランザクションは、レプリケーションを介して前のトランザクションが再生されるのを待ちます。これは、マスターの同時実行性が高い場合、レプリケーション中にスレーブがトランザクションの過負荷で停止する可能性があることを意味します。
これを回避するために、MariaDBとMySQLの両方が並列レプリケーションを提供しています。実装はベンダーやバージョンごとに異なる場合があります。 MySQL 5.6は、クエリがスキーマで区切られている限り、並列レプリケーションを提供します。 MariaDB10.0とMySQL5.7はどちらもスキーマ間での並列レプリケーションを処理できますが、他の境界があります。書き込みが多い場合、並列スレーブスレッドを介してクエリを実行すると、レプリケーションストリームが高速化される可能性があります。ただし、そうでない場合は、従来のシングルスレッドレプリケーションに固執するのが最善です。
スキームの変更
実行中の本番セットアップでスキーマ変更を実行することは、常に苦痛です。これは、DDLの変更がほとんどの場合テーブルをロックし、DDLの変更が適用された後にのみこのロックを解放するという事実と関係があります。 MySQLレプリケーションを介してこれらのDDL変更のレプリケーションを開始すると、さらに悪化し、さらにレプリケーションストリームが停止します。
頻繁に使用される回避策は、最初にスキーマの変更をスレーブノードに適用することです。ステートメントベースのレプリケーションの場合、これは正常に機能しますが、行ベースのレプリケーションの場合、これはある程度まで機能する可能性があります。行ベースのレプリケーションでは、テーブルの最後に追加の列を存在させることができます。最初の列を書き込める限り、問題はありません。最初に変更をすべてのスレーブに適用し、次にスレーブの1つにフェイルオーバーしてから、変更をマスターに適用し、それをスレーブとしてアタッチします。変更に列の中央への挿入または列の削除が含まれる場合、これは行ベースのレプリケーションで機能します。
オンラインスキーマ変更をより確実に実行できるツールがあります。 Percona Online Schema Change(pt-oscとして知られている)は、新しいテーブル構造でシャドウテーブルを作成し、トリガーを介して新しいデータを挿入し、バックグラウンドでデータを埋め戻します。新しいテーブルの作成が完了すると、トランザクション内で古いテーブルを新しいテーブルに交換するだけです。これはすべての場合に機能するわけではありません。特に、既存のテーブルにすでにトリガーがある場合はそうです。
別の方法は、Githubによる新しいGh-ostツールです。このオンラインスキーマ変更ツールは、最初に既存のテーブルレイアウトのコピーを作成し、テーブルを新しいレイアウトに変更してから、プロセスをMySQLレプリカとして接続します。レプリケーションストリームを利用して、元のテーブルに挿入された新しい行を検索すると同時に、テーブルを埋め戻します。埋め戻しが完了すると、元のテーブルと新しいテーブルが切り替わります。当然、新しいテーブルへのすべての操作はレプリケーションストリームにも含まれるため、各レプリカで同時に移行が行われます。
メモリテーブルとレプリケーション
DDLのテーマに取り組んでいますが、一般的な問題はメモリテーブルの作成です。メモリテーブルは非永続テーブルであり、テーブル構造は残りますが、MySQLの再起動後にデータが失われます。マスターとスレーブの両方で新しいメモリテーブルを作成する場合、両方に空のテーブルがあり、これは完全に正常に機能します。いずれかが再起動されると、テーブルが空になり、レプリケーションエラーが発生します。
行ベースのレプリケーションは、スレーブノードのデータが異なる結果を返すと中断し、ステートメントベースのレプリケーションは、既存のデータを挿入しようとすると中断します。メモリテーブルの場合、これは頻繁なレプリケーションブレーカーです。修正は簡単です。データの新しいコピーを作成し、エンジンをInnoDBに変更するだけで、複製が安全になります。
read_only変数をTrueに設定
前に説明したように、スレーブノードに同じデータがないと、レプリケーションが中断する可能性があります。多くの場合、これは、マスターノードではなくスレーブノードのデータを変更した何か(または誰か)によって引き起こされています。マスターノードのデータが変更されると、これはスレーブに複製され、そこで変更を適用できなくなり、複製が中断されます。
これを防ぐのは簡単です。read_only変数をtrueに設定します。これにより、レプリケーションユーザーとルートユーザーを除いて、誰もがデータに変更を加えることができなくなります。ほとんどのフェイルオーバーマネージャーは、このフラグを自動的に設定して、ユーザーがフェイルオーバー中に使用済みマスターに書き込むのを防ぎます。それらのいくつかは、フェイルオーバー後もこれを保持します。
これでも、rootユーザーはスレーブノードで誤ったCRUDクエリを実行する必要があります。これを防ぐために、MySQL 5.7.8以降、rootユーザーがデータを更新できないようにするsuper_read_only変数があります。
GTIDの有効化
MySQLレプリケーションでは、バイナリログの正しい位置からスレーブを起動することが不可欠です。この位置の取得は、バックアップを作成するとき(xtrabackupとmysqldumpがこれをサポートしている)、またはコピーを作成しているノードでスレーブを停止したときに実行できます。 CHANGE MASTER TOコマンドを使用してレプリケーションを開始すると、次のようになります。
mysql> CHANGE MASTER TO MASTER_HOST='x.x.x.x',MASTER_USER='replication_user', MASTER_PASSWORD='password', MASTER_LOG_FILE='master-bin.0001', MASTER_LOG_POS= 04;
間違った場所でレプリケーションを開始すると、悲惨な結果を招く可能性があります。データが二重に書き込まれたり、更新されなかったりする可能性があります。これにより、マスターノードとスレーブノード間でデータドリフトが発生します。
また、マスターをスレーブにフェイルオーバーする場合は、正しい位置を見つけて、マスターを適切なホストに変更する必要があります。 MySQLは、マスターからのバイナリログと位置を保持しませんが、独自のバイナリログと位置を作成します。スレーブノードを新しいマスターに再調整する場合、これは深刻な問題になる可能性があります。フェイルオーバー時のマスターの正確な位置を新しいマスターで見つける必要があります。そうすれば、すべてのスレーブを再調整できます。
この問題を解決するために、グローバルトランザクション識別子(GTID)がOracleとMariaDBの両方に実装されています。 GTIDを使用すると、スレーブの自動調整が可能になり、MySQLとMariaDBの両方で、サーバーが正しい位置を自動的に把握します。ただし、どちらもGTIDを異なる方法で実装しているため、互換性がありません。ある場所から別の場所へのレプリケーションを設定する必要がある場合は、従来のバイナリログポジショニングを使用してレプリケーションを設定する必要があります。また、フェイルオーバーソフトウェアはGTIDを使用しないように注意する必要があります。
結論
トラブルに巻き込まれないようにするための十分なヒントを提供できれば幸いです。これらはすべて、MySQLの専門家による一般的な方法です。彼らはそれを難しい方法で学ぶ必要があり、これらのヒントを使えば、あなたがそうする必要がないことを保証します。
MySQLレプリケーションについて詳しく知りたい場合に役立つ、追加のホワイトペーパーがいくつかあります。
関連するホワイトペーパーMySQLレプリケーションブループリントMySQLレプリケーションブループリントホワイトペーパーには、デプロイメントの詳細、レプリケーションの設定、監視、アップグレード、バックアップの実行、プロキシを使用した高可用性の管理など、レプリケーショントポロジのすべての側面が含まれています。高可用性のためのMySQLレプリケーションのダウンロードこのチュートリアルでは、情報を説明します。 MySQLレプリケーションについて、5.6および5.7で導入された最新機能に関する情報。 ClusterControl.Downloadを使用してレプリケーション設定を迅速に展開および管理する方法についてのより実践的で実用的なセクションもあります。