非同期MySQLレプリケーションのセットアップ:ステップバイステップガイド

この決定版ステップバイステップガイドで、非同期MySQLレプリケーションのセットアップをマスターしましょう。`my.cnf`設定の調整、安全なレプリケーションユーザーアカウントの確立、`mysqldump`を使用した重要な初期データスナップショットの取得など、マスターサーバーとレプリカサーバーの両方を正しく構成する方法を学びます。この記事では、効率的なデータ同期を確保し、スケーラブルなデータベースアーキテクチャのためのレプリケーション遅延を最小限に抑えるための実用的なコマンドと重要なトラブルシューティングのヒントを提供します。

非同期MySQLレプリケーションのセットアップ:ステップバイステップガイド

非同期MySQLレプリケーションは、データベースセットアップにおいて依然として最も有用な構成要素の1つです。読み取りレプリカ、より安全なバックアップ、レポート用コピー、移行ステージング、ディザスタリカバリに使用できます。重要なのは「非同期」という言葉です。ソースはレプリカがトランザクションを適用するのを待たずにコミットします。これにより、ソースがすべてのレプリカ書き込みでブロックされるのを防ぎますが、レプリカが遅延する可能性があることも意味します。

多くのMySQLコマンドで使用されていた古い用語は「master」と「slave」です。新しいバージョンのMySQLでは、SHOW REPLICA STATUSCHANGE REPLICATION SOURCE TOなどのコマンドで「source」と「replica」を使用します。古いシステム、例、スクリプトでは、古いコマンドがまだ表示される場合があります。このガイドでは、説明にsourceとreplicaを使用し、新しいコマンド形式を最初に示し、古い構文が異なる場合は注記を付けます。

この例では、2台のサーバーを使用します。

  • ソース:192.168.1.100
  • レプリカ:192.168.1.101
  • レプリケーションユーザー:repl_user
  • 範囲:すべてのデータベース(意図的にフィルタリングしない限り)

この手順をまだ実行したことがない場合は、最初にテスト環境で行ってください。レプリケーションのセットアップは、すべてがクリーンな状態であれば簡単です。ソースがビジー状態、ダンプに一貫性がない、レプリカに古いデータがすでに含まれている場合、ストレスがかかります。

設定に触れる前に

基本を確認します。

  • 両方のサーバーで互換性のあるMySQLバージョンが実行されていること。
  • レプリカがMySQLポート(通常は3306)でソースに到達できること。
  • 両方のMySQLインスタンスへの管理アクセス権があること。
  • MySQL設定ファイルを編集し、必要に応じてMySQLを再起動できること。
  • レプリカが空であるか、置き換える必要がある既存のデータを正確に把握していること。
  • ソースにバイナリログ用の十分なディスク容量があること。

レプリカホストで、基本的なネットワークアクセスをテストします。

nc -vz 192.168.1.100 3306

ncが利用できない場合は、telnetまたはクラウドプロバイダーの接続ツールを使用します。レプリケーションを構成する前に、ファイアウォール、セキュリティグループ、バインドアドレス、ルーティングを修正します。TCPパスがブロックされている場合、レプリケーションユーザーは役に立ちません。

ソースサーバーの構成

ソースは変更をバイナリログに書き込む必要があります。レプリカはそれらのイベントを読み取り、適用する前にリレーログに保存します。

ソースのMySQL設定ファイルを編集します。一般的な場所は、/etc/mysql/mysql.conf.d/mysqld.cnf/etc/my.cnf、またはそれらのパスからインクルードされるファイルです。[mysqld]の下に次の設定を追加または確認します。

[mysqld]
server-id=1
log-bin=mysql-bin
binlog_format=ROW

server-idは、レプリケーショントポロジ内のすべてのサーバーで一意である必要があります。log-binはバイナリログを有効にします。binlog_format=ROWは、ステートメントの再実行動作に依存するのではなく、行の変更を記録するため、最新のレプリケーションセットアップのほとんどの場合に実用的なデフォルトです。

binlog-do-dbbinlog-ignore-dbには注意してください。フィルタリングは便利に聞こえますが、ステートメントベースの動作はセッションによって選択されたデフォルトデータベースに依存するため、驚くことがあります。フィルタリングされたレプリケーションが必要な場合は、意図的に設計してテストしてください。最初の信頼性の高いセットアップでは、すべてをレプリケートします。

ソースでMySQLを再起動します。

sudo systemctl restart mysql
# または、一部のシステムでは
sudo systemctl restart mysqld

設定を確認します。

SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';

log_binONである必要があります。server_idはゼロ以外で一意である必要があります。

レプリケーションユーザーの作成

レプリカが使用する専用アカウントをソースに作成します。ネットワーク設計で許可される場合は、ホストをレプリカアドレスに制限します。

CREATE USER 'repl_user'@'192.168.1.101' IDENTIFIED BY 'use_a_real_secret_here';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.101';

特権名は、新しいドキュメントでは他の場所で「replica」とよく言及されていますが、MySQLのGRANTでは依然としてREPLICATION SLAVEです。

レプリカホストからログインをテストします。

mysql -h 192.168.1.100 -u repl_user -p

これが失敗した場合は、今すぐ認証とネットワークを修正します。一般的な原因は、ソースのbind-address、ファイアウォールルール、ユーザーホストの不一致、DNSが異なるアドレスに解決されること、および古いクライアントとの認証プラグインの非互換性です。

レプリカサーバーの構成

レプリカで、異なるserver-idを構成します。リレーログは通常、レプリケーションのために自動的に有効になりますが、明示的に名前を付けると操作が明確になります。

[mysqld]
server-id=2
relay_log=mysql-relay-bin
read_only=ON

より強力な保護のために、セットアップ後にsuper_read_only=ONを検討してください。read_onlyは、すべての特権アカウントが書き込むのを止めるわけではありません。super_read_onlyは、アプリケーションの書き込みを決して受け入れるべきではないレプリカにとってより安全ですが、特定の管理タスクのために一時的にオフにする必要がある場合があります。

レプリカでMySQLを再起動して確認します。

sudo systemctl restart mysql
SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'read_only';

一貫性のある初期スナップショットを取得する

レプリカは、特定のバイナリログ位置に一致するデータコピーから開始する必要があります。スナップショットと位置が一致しない場合、レプリケーションは開始しても正しく動作しない可能性があります。

InnoDB主体のデータベースの場合、mysqldump --single-transactionが通常最も簡単な一貫性のある方法です。トランザクションテーブルに対して長期間のグローバル読み取りロックを回避します。新しいMySQLバージョンでは--source-data=2を含めて、ダンプがソースのバイナリログファイルと位置をコメント行として記録するようにします。古いバージョンでは--master-data=2を使用します。

ソースに接続できる信頼できるホストでこれを実行します。

mysqldump -h 192.168.1.100 -u root -p \
  --all-databases \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --source-data=2 \
  > source_dump.sql

MySQLのバージョンが--source-dataをサポートしていない場合は、次を使用します。

mysqldump -h 192.168.1.100 -u root -p \
  --all-databases \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --master-data=2 \
  > source_dump.sql

--single-transactionはInnoDBの一貫性には安全ですが、非トランザクションのMyISAMテーブルを同じように一貫性のあるものにはしません。まだMyISAMテーブルがある場合は、メンテナンスウィンドウを計画するか、一貫性のあるスナップショットを提供する別のバックアップ方法を使用してください。

記録されたレプリケーション座標についてダンプを確認します。

grep -m 1 -E "CHANGE (MASTER|REPLICATION SOURCE)" source_dump.sql

バイナリログファイルと位置を含むコメント行が表示されるはずです。それを保持します。GTIDベースのレプリケーションを選択しない限り、レプリカをソースに向けるときに使用します。

レプリカにスナップショットをインポートする

通常の安全な方法を使用して、ダンプをレプリカに転送します。

scp source_dump.sql db-replica:/tmp/source_dump.sql

レプリカで、既存の本番環境のようなデータセットに誤って書き込んでいないことを確認します。このレプリカをクリーンなコピーにする必要がある場合は、移行計画で置き換えるように指示されているものだけをドロップして再作成します。次にインポートします。

mysql -u root -p < /tmp/source_dump.sql

大規模なダンプの場合は、screenまたはtmuxでインポートを実行し、ディスク容量を監視します。/var/lib/mysqlまたは/tmpがいっぱいになったためにインポートが失敗すると、時間を浪費し、半分ロードされたレプリカが残る可能性があります。

レプリカをソースに向ける

MySQL 8.0.23以降では、CHANGE REPLICATION SOURCE TOを使用します。

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='192.168.1.100',
  SOURCE_USER='repl_user',
  SOURCE_PASSWORD='use_a_real_secret_here',
  SOURCE_LOG_FILE='mysql-bin.000001',
  SOURCE_LOG_POS=1234;

ファイルと位置をダンプの値に置き換えます。古い構文を使用している場合、同等のものは次のとおりです。

CHANGE MASTER TO
  MASTER_HOST='192.168.1.100',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='use_a_real_secret_here',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=1234;

環境がGTIDを使用している場合、セットアップは異なります。通常、両方のサーバーでGTIDモードを構成し、GTID状態を保持するダンプを復元し、ファイルと位置の代わりにSOURCE_AUTO_POSITION=1を使用します。GTIDとファイル位置の指示を軽率に混在させないでください。1つのアプローチを選択してテストしてください。

GTIDレプリケーションに関する簡単な注意

GTIDレプリケーションは、MySQLがバイナリログファイルと位置を手動で管理させる代わりに、グローバルトランザクションIDでトランザクションを追跡するため、セットアップ後の運用が容易になることがよくあります。これは、フェイルオーバー、ソース変更、レプリカ再構築中に特に役立ちます。

だからといって、移行の途中で軽率にオンにすべきというわけではありません。両方のサーバーで互換性のあるGTID設定が必要であり、バックアップまたはダンププロセスで正しいGTID状態を保持する必要があります。一般的なパターンは、次のように構成することです。

[mysqld]
gtid_mode=ON
enforce_gtid_consistency=ON

次に、GTID対応のダンプを復元した後、次のようにレプリカを構成します。

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='192.168.1.100',
  SOURCE_USER='repl_user',
  SOURCE_PASSWORD='use_a_real_secret_here',
  SOURCE_AUTO_POSITION=1;

これは、ソースとレプリカのGTID履歴がクリーンで理解されている場合にのみ使用してください。確信が持てない場合は、最初のセットアップではファイルと位置によるレプリケーションの方が理解しやすいです。最悪の選択は、レプリケーションが開始されるまで両方のアプローチの例を混在させることですが、トランザクション履歴はあなたが考えているものとは異なります。

レプリケーションを開始します。

START REPLICA;

古い構文:

START SLAVE;

ステータスを確認します。

SHOW REPLICA STATUS\G

古い構文:

SHOW SLAVE STATUS\G

主要なフィールドは次のとおりです。

フィールド 正常な値 意味
Replica_IO_Running Yes レプリカが接続してバイナリログイベントをフェッチできる。
Replica_SQL_Running Yes レプリカがリレーログイベントを適用できる。
Last_IO_Error ネットワーク、資格情報、またはソースログの問題がここに表示されます。
Last_SQL_Error データの競合や適用エラーがここに表示されます。
Seconds_Behind_Source 低い、または減少中 おおよその遅延インジケーター。

古い出力では、Slave_IO_RunningSlave_SQL_RunningSeconds_Behind_Masterが使用されます。

小さな書き込みでテストする

スレッドがYesと言った後で勝利を宣言しないでください。ソースに小さなテストテーブルを作成するか、既存のテストスキーマに無害な行を挿入してから、レプリカに表示されることを確認します。

ソースでの例:

CREATE DATABASE IF NOT EXISTS repl_check;
CREATE TABLE IF NOT EXISTS repl_check.heartbeat (
  id INT PRIMARY KEY,
  checked_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
REPLACE INTO repl_check.heartbeat (id) VALUES (1);

レプリカで:

SELECT * FROM repl_check.heartbeat;

これにより、間違ったソースを指している、データベースをフィルタリングしている、古い座標を使用しているなどの単純なミスを検出できます。

レプリケーションチャネルを保護する

レプリケーショントラフィックが信頼できないネットワークを通過する場合は、TLSを要求します。プライベートネットワーク内であっても、ネットワーク境界は時間の経過とともに変化するため、多くのチームは現在、暗号化されたデータベーストラフィックを好みます。

少なくとも、レプリケーションユーザーとチャネルを作成して、資格情報がアプリケーションアカウントと共有されないようにします。TLSベースのチャネルの場合は、MySQLのバージョンに従って証明書を構成し、レプリケーションソース構成にSSLオプションを含めます。正確なオプションはバージョンと証明書ポリシーによって異なりますが、意図は同じです。レプリカは、期待されるソースに接続していることを確認し、転送中の資格情報と行の変更を保護する必要があります。

また、レプリケーションユーザーの権限を狭く保ちます。広範なDDLまたはDMLアクセスは必要ありません。誰かがそのパスワードを入手した場合、影響範囲はレプリケーションログの読み取りに限定され、アプリケーションデータの書き込みには及ばないようにする必要があります。

一般的なセットアップの問題

Replica_IO_RunningNoの場合、レプリカはイベントをフェッチできません。以下を確認します。

  • SOURCE_HOSTが正しいこと。
  • ソースが期待されるアドレスとポートでリッスンしていること。
  • ファイアウォールとセキュリティグループがトラフィックを許可していること。
  • レプリケーションユーザーホストがレプリカのソースIPと一致していること。
  • パスワードと認証プラグインがレプリカのクライアント/サーバーバージョンで機能すること。
  • 要求されたバイナリログファイルがソースにまだ存在すること。

Replica_SQL_RunningNoの場合、レプリカはイベントをフェッチしたが適用できなかったことを意味します。Last_SQL_Errorを確認します。重複キーは、多くの場合、レプリカが正確に一致するスナップショットから初期化されなかったか、誰かがレプリカに直接書き込んだことを意味します。行の欠落は、多くの場合、データのドリフトを意味します。SQL_SLAVE_SKIP_COUNTERでトランザクションをスキップするとスレッドが動く可能性がありますが、レプリカが間違った状態になる可能性もあります。失敗したトランザクションを理解し、 divergence リスクを受け入れる場合にのみ使用してください。

セットアップ直後に遅延が大きい場合は、レプリカに追いつかせ、Seconds_Behind_Sourceが減少するかどうかを監視します。大規模なダンプインポートの後にレプリケーションを開始すると、バックログが残る可能性があります。遅延が減少する代わりに増加する場合は、レプリカのディスクI/Oとソースの書き込みボリュームを調査します。

セットアップ後にレプリカの健全性を維持する

レプリカがメンテナンスと停止を乗り切れるように、ソースでバイナリログの保持を構成します。最新のMySQLではbinlog_expire_logs_secondsを使用します。

[mysqld]
binlog_expire_logs_seconds=604800

この例では、ログを約7日間保持します。リカバリのニーズとディスク容量に基づいて値を選択します。古いシステムではexpire_logs_daysを使用する場合があります。

レプリケーションの状態と遅延を監視します。少なくとも、いずれかのレプリケーションスレッドが停止した場合、遅延が許容範囲を超えた場合、バイナリログがパージされていないためにソースのディスク使用量が増加した場合にアラートを出します。データ整合性チェックには、多くのチームがPercona Toolkitのpt-table-checksumpt-table-syncなどのツールを使用しますが、本番規模のデータで実行する前に注意深くテストしてください。

最後に、レプリカが読み取り専用であり、追いつき、監視されていることを確認するまで、アプリケーショントラフィックをレプリカから遠ざけてください。誤った書き込みを受け入れるレプリカは、レプリカがないよりも悪いです。なぜなら、フェイルオーバーまたはリカバリまで損傷が隠れたままになる可能性があるからです。

非同期レプリケーションは、開始スナップショット、バイナリログ座標、権限、および監視がすべて一致している場合に適切に機能します。失敗したセットアップのほとんどは、これらのいずれかが確認される代わりに想定されていることに起因します。