症状

MySQL レプリケーションで Seconds_Behind_Master が増加し続ける、または高い値のまま減少しない

結論:まずこれを確認

  1. SHOW SLAVE STATUS\GSlave_IO_RunningSlave_SQL_Running が両方 Yes か確認
  2. Seconds_Behind_Master の値と推移を確認(増加中か、一定か)
  3. スレーブ側の CPU・ディスク I/O 負荷を確認

トラブルシューティングフロー

    flowchart TD
    A[Seconds_Behind_Master が高い] --> B{Slave_IO_Running は Yes?}
    B -->|No| C[ネットワーク/マスター接続の問題]
    B -->|Yes| D{Slave_SQL_Running は Yes?}
    D -->|No| E[SQL スレッドエラーを確認]
    D -->|Yes| F{遅延は増加中?}
    F -->|Yes| G[スレーブの処理能力不足]
    F -->|No| H{大量の更新があった?}
    H -->|Yes| I[一時的な遅延 - 待機]
    H -->|No| J[長時間クエリ/ロック確認]
    
    C --> K[マスター側ログ・ネットワーク確認]
    E --> L[Last_SQL_Error を確認]
    G --> M[スレーブスペック/設定確認]
    J --> N[SHOW PROCESSLIST 確認]
  

よくある原因

  • マスターでの大量更新 - バッチ処理やデータ移行で一時的に遅延が発生
  • スレーブのディスク I/O 不足 - HDD使用時やIOPS制限がある環境で発生しやすい
  • スレーブの CPU 不足 - シングルスレッドの SQL スレッドがボトルネックになる
  • 長時間実行クエリ - マスターで実行された ALTER TABLE などがスレーブで再実行される
  • ネットワーク帯域不足 - バイナリログの転送が追いつかない
  • テーブルロック競合 - スレーブ上の読み取りクエリとの競合
  • 不適切な設定 - sync_binloginnodb_flush_log_at_trx_commit の設定不整合

確認手順

ステップ1: レプリケーション状態を確認する

    mysql -e "SHOW SLAVE STATUS\G" | grep -E "(Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_SQL_Error|Master_Log_File|Relay_Master_Log_File)"
  

🔍 チェックポイント: Slave_IO_Running: YesSlave_SQL_Running: Yes であれば基本的な接続は正常

ステップ2: 遅延の推移を確認する

    # 5秒ごとに10回確認
for i in {1..10}; do
  mysql -e "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master"
  sleep 5
done
  

🔍 チェックポイント: 値が増加中なら処理が追いついていない、一定なら安定しつつも遅れている状態

ステップ3: スレーブのリソース状況を確認する

    # CPU使用率
top -bn1 | head -20

# ディスクI/O
iostat -x 1 5

# MySQL プロセスの状態
mysql -e "SHOW PROCESSLIST\G" | grep -A5 "system user"
  

🔍 チェックポイント: CPU使用率が100%に張り付いている、iowait が高い場合はリソース不足

ステップ4: 実行中の処理を確認する

    mysql -e "SHOW PROCESSLIST\G" | grep -B2 -A8 "State:"
  

🔍 チェックポイント: State: Waiting for table metadata lock などが表示されていればロック競合の可能性

ステップ5: バイナリログの差分を確認する

    mysql -e "SHOW SLAVE STATUS\G" | grep -E "(Master_Log_File|Read_Master_Log_Pos|Relay_Master_Log_File|Exec_Master_Log_Pos)"
  

🔍 チェックポイント: Master_Log_FileRelay_Master_Log_File が大きく異なる場合、I/O スレッドの転送も遅れている

ステップ6: マスター側の更新量を確認する

マスター側で実行:

    mysql -e "SHOW MASTER STATUS\G"
mysql -e "SHOW GLOBAL STATUS LIKE 'Com_%'" | grep -E "(insert|update|delete)"
  

🔍 チェックポイント: マスターで大量の更新があった直後は遅延が発生しやすい

NG行動(やってはいけないこと)

  • 遅延中にスレーブを再起動する - リレーログの再取得が必要になり、さらに遅延が増える可能性
  • STOP SLAVE を安易に実行する - 遅延がリセットされず、再開時に混乱の原因になる
  • マスターの binlog を削除する - スレーブが追いつく前に削除すると復旧不能になる
  • 遅延中にスレーブでスキーマ変更する - レプリケーション不整合の原因になる
  • Seconds_Behind_Master = 0 だけを見て安心する - I/O スレッドが停止していても 0 になる場合がある

よくある質問(FAQ)

Q1: Seconds_Behind_Master が NULL になっている場合は?

A: Slave_IO_Running または Slave_SQL_RunningNo になっている可能性が高い。SHOW SLAVE STATUS\GLast_IO_Error または Last_SQL_Error を確認する

Q2: 遅延を許容できる範囲に抑えるにはどうする?

A: スレーブのスペック向上、並列レプリケーション(slave_parallel_workers)の設定、SSD への換装などを検討する。根本的にはマスターの更新量削減が有効

Q3: pt-heartbeat などのツールを使うべき?

A: Seconds_Behind_Master は精度に問題がある場合があるため、正確な遅延監視が必要なら pt-heartbeat(Percona Toolkit)の導入を検討する

関連するエラー・症状

準備中

解決しない場合