レプリケーションが「正常」なのに、データが「異常」な時
午前2時、Slackの通知が鳴り止みません。モニタリングシステムが「データドリフト(Data Drift)」を検知しました。Seconds_Behind_Masterは「0」を表示しており、レプリケーションは正常に動いているように見えますが、Slave側のレポートデータがMasterと全く食い違っています。これは非常に厄介な状況です。レプリケーションのプロセス自体は走っていますが、中身がバラバラになってしまっているのです。
インフラエンジニア(Ops)なら、一度はこの光景を目にしたことがあるでしょう。誰かが誤ってSlaveに直接データを書き込んでしまったのかもしれません。あるいは、稀なバグによってトランザクションが正しくレプリケートされなかった可能性もあります。ここで問題となるのは、数百GBものデータをダンプしてリストアすることなく、どのテーブルが不整合を起こしているか、どうやって正確に特定するかということです。
なぜ従来の方法は失敗するのか?
通常、データの不整合を発見した際、私たちは2つの方法を思い浮かべがちです:
- mysqldumpを使用する: Master from ダンプしてSlaveにリストアする方法です。500GBクラスのデータベースでは、ダンプのためのテーブルロックやネットワーク転送は悲劇を招きます。システムが1時間以上ダウンタイムに陥る可能性があります。
- COUNT(*)で比較する: 行数を数えるだけの方法です。行数が同じでも、中身(価格や注文ステータスなど)が書き換わっている場合には全くの無力です。
そんな時、Percona Toolkitの強力なコンビである pt-table-checksum と pt-table-sync が救世主となります。これを使えば、システムをオンライン状態(24/7)に保ったままデータドリフトに対処できます。
Percona Toolkitのスマートな仕組み
pt-table-checksum は、データをローカルマシンに持ってきて比較するわけではありません。代わりに、テーブルを小さな「チャンク(chunk)」に分割し、Master上でチェックサムを計算するSQLを実行します。レプリケーションの仕組みにより、これらのコマンドは自動的にSlaveでも実行されます。最後に、ツールが両者のチェックサム結果を比較するだけで、どのテーブルにエラーがあるかを指し示してくれます。
クイックインストール
Ubuntu/Debianの場合は、以下のコマンドひとつで完了します:
sudo apt-get install percona-toolkit
CentOS/RHELの場合は、yumを使用します:
sudo yum install percona-toolkit
ステップ1:pt-table-checksumで不整合なテーブルを特定する
開始する前に、SUPER および REPLICATION CLIENT 権限を持つ percona_user を作成してください。このユーザーは、一時的な結果を保存するために percona データベースへのフルアクセス権限が必要です。
以下のコマンドでチェックを実行します:
pt-table-checksum h=master_ip,u=percona_user,p=password \
--databases=my_production_db \
--replicate=percona.checksums \
--create-replicate-table \
--no-check-replication-filters
オプションの解説:
--replicate: 結果をpercona.checksumsテーブルに保存します。--create-replicate-table: テーブルが存在しない場合に自動作成します。--no-check-replication-filters: MySQL設定でフィルタリングされているテーブルも強制的にチェックします。
実行後、DIFFS カラムを確認してください。この数値が0より大きい場合、そのテーブル의 データは確実に不整合を起こしています。
Tips: 1,000万行を超えるような大きなテーブルの場合、私はいつも --max-load Threads_running=25 を追加します。サーバーの負荷が高くなりすぎた場合、ツールが自動的に一時停止してシステムを保護してくれます。
ステップ2:pt-table-syncによるデータの同期
不整合なテーブル(例:orders)が特定できたら、次はその修正です。pt-table-sync は自動的に REPLACE や DELETE 文を生成し、Slaveの状態をMasterと同じにします。
いきなり実行してはいけません。まずは「ドライラン(dry run)」モードで、ツールが何を修正しようとしているかを確認します:
pt-table-sync --print \
--replicate=percona.checksums \
h=master_ip,u=percona_user,p=password \
h=slave_ip
表示されたSQL文に問題がなければ、実行コマンドを叩きます:
pt-table-sync --execute \
--replicate=percona.checksums \
h=master_ip,u=percona_user,p=password \
h=slave_ip
注意:このプロセスはSlaveに直接データを書き込みます。テーブルが非常に大きい場合は、サーバーのI/Oと負荷を注意深く監視してください。
本番環境で避けるべき「落とし穴」
大規模なデータベースを何度も扱ってきた経験から、4つの重要な注意点を挙げます:
- プライマリキー(Primary Key)が必須: このツールはインデックスに基づいて動作します。PKがないテーブルでは、フルテーブルスキャンが発生し、深刻なラグやテーブルロックを引き起こします。
- ネットワーク遅延: チェックサムを送信するだけとはいえ、MasterとSlaveが異なるリージョン(例:東京とバージニア)にある場合、プロセスに時間がかかることがあります。
- トリガー(Triggers)に注意: Slave側に他のテーブルを自動更新するトリガーがある場合、同期処理が予期せぬドミノ倒し的な影響を及ぼす可能性があります。
- 書き込み権限: 実行ユーザーがSlaveの
read_only = 1設定をバイパスできるよう、SUPER権限を持っていることを確認してください。
まとめ
MySQLのデータ不整合は、長期間運用していれば遅かれ早かれ直面する問題です。ダンプとリストアに丸一日費やす代わりに、Percona Toolkitをマスターすることで、スマートかつプロフェッショナルに問題を解決できます。次に真夜中に呼び出された時は、落ち着いてコマンドを入力しましょう。データはすぐに元通り同期されるはずです。

