停電後の MySQL レプリケーションの問題

停電後の MySQL レプリケーションの問題

データセンターで停電が発生したため、スレーブ MySQL データベースが動作しなくなりました。

これはスレーブの 1 つのログに記録されています。

100118 10:05:56 [Note] Slave I/O thread: connected to master 'repl@db1:3306',  replication started in log 'bin-log.004712' at position 724207814
100118 10:05:56 [ERROR] Error reading packet from server: Client requested master to start replication from impossible position ( server_errno=1236)
100118 10:05:56 [ERROR] Got fatal error 1236: 'Client requested master to start replication from impossible position' from master when reading data from binary log
100118 10:05:56 [Note] Slave I/O thread exiting, read up to log 'bin-log.004712', position 724207814

コンソールにはさらに詳しい情報が表示されます。

mysql> show slave status \G;
*************************** 1. row ***************************
             Slave_IO_State:
                Master_Host: db1
                Master_User: repl
                Master_Port: 3306
              Connect_Retry: 10
            Master_Log_File: bin-log.004712
        Read_Master_Log_Pos: 724207814
             Relay_Log_File: mysqld-relay-bin.000105
              Relay_Log_Pos: 98
      Relay_Master_Log_File: bin-log.004712
           Slave_IO_Running: No
          Slave_SQL_Running: Yes
            Replicate_Do_DB: mmplive1,mmpjcr,fui
        Replicate_Ignore_DB:
         Replicate_Do_Table:
     Replicate_Ignore_Table:
    Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
                 Last_Errno: 0
                 Last_Error:
               Skip_Counter: 0
        Exec_Master_Log_Pos: 724207814
            Relay_Log_Space: 98
            Until_Condition: None
             Until_Log_File:
              Until_Log_Pos: 0
         Master_SSL_Allowed: No
         Master_SSL_CA_File:
         Master_SSL_CA_Path:
            Master_SSL_Cert:
          Master_SSL_Cipher:
             Master_SSL_Key:
      Seconds_Behind_Master: NULL
1 row in set (0.00 sec)

ERROR:
No query specified

マスターの bin ログを見ると、次のようになっています。

-rw-rw---- 1 mysql mysql  724200412 Jan 18 09:22 bin-log.004712
-rw-rw---- 1 mysql mysql       1904 Jan 18 09:27 bin-log.index
-rw-rw---- 1 mysql mysql    5046830 Jan 18 11:22 slow-log
-rw-rw---- 1 mysql mysql  198249613 Jan 18 11:24 bin-log.004713
  1. スレーブ ステータスでは、バイナリ ログ bin-log.004712 の Exec_Master_Log_Pos と Read_Master_Log_Pos が両方とも 724207814 であることがわかります。この値はバイナリ ログ ファイル内のバイト位置であると理解しています。
  2. bin-log.004712 ファイルは 724200412 バイトしかないため、スレーブは、ファイル (ext3 fs、RAID-10、RHEL5 上) に実際に保存されている作業よりも 7402 バイト多く作業を行ったと認識します。そのため、ログの位置が不可能であるなどのエラー メッセージが表示されます。

奴隷を治す最善の方法は何ですか?

検討しているオプション:

  1. 各スレーブを次の bin-log ファイル (bin-log.004713) の位置 0 を指すように設定して、そのままにしておきます。ただし、それがどれほど安全か、またはどれほどのデータが失われる可能性があるかはわかりません。
  2. 代わりに、完全なバックアップと復元 (InnoDB テーブルのテーブル ロックによるダウンタイムが想定されます) を実行する必要がありますか? 可能であれば、それを避けたいと思います。

アップデート:

私は別のオプションを忘れていました。それは、各スレーブの実行位置を少しだけ戻して、bin-log.004712 からすでに処理したコマンドを複製しようとするというものでした。

答え1

私は最初の選択肢を選びました。

これは、スレーブが主キーと競合する挿入を試み始めるまで機能しました。スレーブは、前述のように、マスターのバイナリログが保持していたよりも多くの作業を実行しました。私が予想していなかった点の1つは、スレーブにマスターにないデータが含まれていたことです。つまり、スレーブは、マスターが保持していた停電の前にいくつかのトランザクションを保持していました。していなかった持続した。

私の場合、これらのトランザクションは支払い関連でも類似のものでもなかったため、スレーブからデータを削除し (その結果、マスターには存在しなかった一部のデータが失われます)、レプリケーションを再度実行しました。これにより、スレーブは完全に最新の状態になりました。データがより重要だった場合、自動増分オフセットが十分にあり、データを手動で調整して参照整合性が損なわれないようにする余裕があります。ありがたいことに、この場合はそれを行う必要はありませんでした。

このような状況にあった (パッシブ) マスター マスター構成のマシンに対して、私は同様のアプローチを選択しました。パッシブ マスター マスターとは、すべての書き込みが行われるアクティブ マスター (serverA) と、ダウンタイムなしでスキーマ更新を実行できるようにするために配置されているパッシブ マスター (serverB) があることを意味します。アクティブ マスター (serverA) のデータが真の値として選択されましたが、これにより、重要ではないとみなされたいくつかの永続トランザクションが失われることがわかりました。

  • スレーブ上のログ ファイルと位置を変更しました。

    CHANGE MASTER MASTER_LOG_FILE='bin-log.004713', MASTER_LOG_POS=0; -- on serverB
    
  • 他のスレーブと同様に、主キー制約違反で失敗するまで、パッシブ マスター (serverB) でスレーブ レプリケーションを再起動しました。

     START SLAVE; -- on serverB
    
  • パッシブ マスター (serverB) からアクティブ マスター (serverA) へのスレーブ レプリケーションを停止しました。

    STOP SLAVE; -- on serverA
    
  • serverA のマスターに存在しなかったスレーブ (serverB) の行を削除します。

    DELETE FROM SOME_TABLE WHERE ID IN (???,????); -- on serverB
    SHOW MASTER STATUS\G; -- get the new master log position on serverB
    
  • アクティブ マスター (serverA) のスレーブ実行位置を移動して、パッシブ マスター (serverB) からの削除をスキップします。

    CHANGE MASTER TO MASTER_LOG_POS=???; --on serverA; use the value just obtained from serverB
    
  • アクティブ マスター (serverA) とパッシブ マスターの両方でレプリケーションを再起動します。

    START SLAVE; -- on both machines. serverA does nothing and serverB starts catching up.
    

答え2

スレーブがマスターの正確なレプリカであることがどの程度重要かによって異なります。最初のオプションはある程度は機能しますが、スレーブがマスターからの情報を失う可能性が高くなります。データが一時的であるなどの理由でそれを許容できる場合は、それを選択してください。スレーブが適切なレプリカであることが重要である場合は、2 番目のオプションがおそらく唯一の選択肢です。残念ながら、MySQL レプリケーションは予期しない中断を許容しません。このような問題は、レプリケーション アーキテクチャで望んでいるよりもはるかに頻繁に発生することがわかりました。

関連情報