MySQL のレプリケーション入門
MySQL のレプリケーションは、あるサーバー(ソース)のデータを別のサーバー(レプリカ)に自動的に複製する仕組みだ。読み取り負荷の分散、障害時のフェイルオーバー、バックアップの取得など、本番運用では欠かせない技術となっている。
レプリケーションの基本的な仕組み
レプリケーションは、ソースサーバーで発生したデータ変更をレプリカサーバーに伝播させることで成り立つ。その中核にあるのがバイナリログ(binlog)だ。
ソースで INSERT / UPDATE / DELETE が実行される
変更内容がバイナリログに記録される
レプリカが I/O スレッドでバイナリログを取得し、リレーログに書き込む
レプリカの SQL スレッドがリレーログを再生してデータに反映する
この一連の流れにおいて、レプリカ側では 2 つのスレッドが協調して動作する。I/O スレッドはソースとの通信を担当し、SQL スレッドは取得した変更の適用を担当している。それぞれが独立して動くことで、ネットワーク遅延とデータ適用の処理を分離できる設計になっている。
レプリケーションの種類
MySQL のレプリケーションには、変更の記録方式によっていくつかの種類が存在する。
実行された SQL 文そのものをバイナリログに記録する方式。ログのサイズが小さい利点があるが、NOW() や RAND() のような非決定的関数を含む文では、ソースとレプリカで結果が異なる可能性がある。
変更された行データそのものを記録する方式。非決定的な関数でも正確に複製できるが、大量行の更新ではログサイズが大きくなりやすい。MySQL 8.0 ではこちらがデフォルトとなっている。
さらに MIXED 形式も用意されており、通常はステートメントベースで記録しつつ、非決定的な処理が含まれる場合だけ自動的に行ベースに切り替わる。実運用では RBR か MIXED のいずれかを選ぶケースが多い。
非同期レプリケーションと準同期レプリケーション
標準のレプリケーションは非同期で動作する。ソースはバイナリログに書き込んだ時点でトランザクションを完了させ、レプリカがそれを取得・適用するのを待たない。この方式はパフォーマンスに優れるが、ソースが障害でダウンした場合にレプリカへまだ伝わっていない変更が失われるリスクがある。
このリスクを軽減するために MySQL では準同期レプリケーション(semisynchronous replication)が提供されている。
ソースがコミット時に、少なくとも 1 台のレプリカがリレーログへの書き込みを完了するまで待機する方式。データ損失リスクを低減できるが、その分レイテンシが増加する。
準同期レプリケーションはプラグインとして提供されており、ソースとレプリカの両方にインストールして有効化する必要がある。タイムアウトを設定でき、一定時間内にレプリカから応答がなければ非同期モードに自動でフォールバックする仕組みになっている。
基本的な構築手順
レプリケーションの構築は、ソースとレプリカの双方で設定を行う。まずソース側の my.cnf でバイナリログとサーバー ID を設定する。
-- ソース側の設定(my.cnf)
-- [mysqld]
-- server-id = 1
-- log-bin = mysql-bin
-- binlog-format = ROW
-- レプリケーション用ユーザーの作成
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;続いてレプリカ側でもサーバー ID を設定したうえで、ソースへの接続情報を登録して開始する。
-- レプリカ側の設定(my.cnf)
-- [mysqld]
-- server-id = 2
-- relay-log = relay-bin
-- read-only = ON
-- レプリカでソースを指定して開始
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.1.10',
SOURCE_USER = 'repl_user',
SOURCE_PASSWORD = 'repl_password',
SOURCE_LOG_FILE = 'mysql-bin.000001',
SOURCE_LOG_POS = 154;
START REPLICA;read-only = ON を設定しておくと、レプリカへの意図しない書き込みを防止できる。本番環境では必ず有効にしておくべき設定だ。
レプリケーションの状態確認
レプリケーションが正常に動作しているかどうかは SHOW REPLICA STATUS で確認できる。
SHOW REPLICA STATUS\G出力結果のうち、特に注目すべき項目がいくつかある。
| 項目 | 意味 | 正常値 |
|---|---|---|
| Replica_IO_Running | I/O スレッドの状態 | Yes |
| Replica_SQL_Running | SQL スレッドの状態 | Yes |
| Seconds_Behind_Source | レプリカの遅延秒数 | 0 に近い値 |
Seconds_Behind_Source が増加し続けている場合、レプリカの処理がソースの変更に追いついていない状態を示す。原因としてはレプリカのハードウェア性能不足や、重いクエリの実行などが考えられる。
GTID ベースのレプリケーション
MySQL 5.6 以降では GTID(Global Transaction Identifier)を使ったレプリケーションが利用可能になった。GTID はすべてのトランザクションにグローバルで一意な識別子を付与する仕組みで、従来のバイナリログファイル名とポジション指定に比べて管理が大幅に簡素化される。
-- GTID を有効にする設定(my.cnf)
-- [mysqld]
-- gtid-mode = ON
-- enforce-gtid-consistency = ON
-- GTID ベースのレプリカ設定
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.1.10',
SOURCE_USER = 'repl_user',
SOURCE_PASSWORD = 'repl_password',
SOURCE_AUTO_POSITION = 1;
START REPLICA;GTID を使うことで、フェイルオーバー時にレプリカを新しいソースに切り替える際のポジション計算が不要になる。複数台構成での運用負荷を大きく軽減してくれる機能といえる。
運用上の注意点
レプリケーションを安定して運用するためにはいくつかのポイントを押さえておく必要がある。
レプリケーションはデータの冗長性と可用性を高めるための基盤技術だが、万能ではない。レプリカへの反映には必ず遅延が伴うため、リアルタイム性が求められる読み取りにはソースを使うなど、アプリケーション側での使い分けも重要になってくる。












