読者です 読者をやめる 読者になる 読者になる

惑星間レプリケーションとRDSのレプリケーション

RDSのMultiAZでは、データベースの障害時の影響を最小化するために同期レプリケーションを行っています。一方、リードレプリカであるスレーブとのレプリケーションは非同期で行っています。
非同期レプリケーションでは、"パケット通信時間 + スレーブでの更新反映の時間 + α"分のレプリケーション遅延が発生します。RDSでは、データセンタ間を高速な回線でつなぐことでネットワーク通信を高速化し遅延を減らしています、が遅延がなくなるというわけではなく、更新頻度、更新処理をスレーブに反映させるのにかかる時間によっては、遅延は常に発生していますし、大きな遅延にもなりえます。
そして、その遅延が発生しうる仕組み上、マスターとスレーブ間でどの時点までの更新が反映されているかは異なりうるため、その更新のズレがあるときに特定の操作が行われた場合発生しうるレプリケーションエラーがいくつかあります。

今回話すこと

RDSのレプリケーション。とくに、レプリケーションエラーまわりについて(mysql 5.5)

話さないこと

惑星間レプリケーション



!


(リードレプリカであるスレーブの状態を確認するには、"SHOW SLAVE STATUS"コマンドが使えます)

mysql> SHOW SLAVE STATUS\G


f:id:karahiyo:20151019214553g:plain



Errno:1062 レプリケーションエラー

スレーブでバイナリログの反映処理に失敗した場合に発生し、これによってSQLスレッドが停止し、そのスレーブとマスタ間のレプリケーションが停止します。発生しうるケースは、スレーブ側を直接更新した場合、STATEMENTベースのレプリケーションで非決定性の更新クエリを実行した場合、長いトランザクション、バイナリログの不整合(例えば、Multi-AZ設定のマスタのフェイルオーバを原因とした)など。

以下は、リードレプリカで"duplicate entry"エラーが発生しているときの、"SHOW SLAVE STATUS"の出力一部。

mysql> show slave status\G
*************************** 1. row ***************************
   Last_Errno: 1062
   Last_Error: Error 'Duplicate entry '123456789-2101-01-01 0:00:00' for key 'PRIMARY'' on query. Default database: 'test'. Query: 'INSERT INTO ...'

参考:

応急処置

エラーの内容を確認し、レプリケーションエラーをスキップします。それには、"CALL mysql.rds_skip_repl_error" 手続きが使えます。mysqlでいう、SQL_SLAVE_SKIP_COUNTERにあたります。
複数のレプリケーションエラーがある場合、最初のエラー(Last_Error)のみスキップします。

mysql> show slave status\G
*************************** 1. row ***************************
   Slave_IO_State: Waiting for master to send event
       Last_Errno: 1062
       Last_Error: Error 'Duplicate entry '123456789-2101-01-01 0:00:00' for key 'PRIMARY'' on query. Default database: 'test'. Query: 'INSERT INTO ...'
mysql> call mysql.rds_skip_repl_error;
mysql> show slave status\G


参考:

予防

1. バイナリログを同期する

sync_binlog =1
innodb_support_xa=1
innodb_flush_logs_at_trx_commit=1

参考:


ちなみに、RDSのmasterのbinlog_formatはMixedから変更できません。

現時点では、Amazon RDS for MySQL は行ベースのレプリケーションへの明示的な変更をサポートしていません。

よくある質問 - Amazon RDS(リレーショナルデータベースサービス Amazon Relational Database Service) | アマゾン ウェブ サービス(AWS 日本語)

!

Errno:1236 レプリケーションIOエラー

スレーブがマスタに存在しないバイナリログの位置を指定しています、というエラーです。IOスレッドが停止し、結果そのスレーブとマスタ間のレプリケーションが停止します。
発生しうるケースは、スレーブ側でバイナリログの位置の指定を間違えた場合、マスタ側でバイナリログ情報を破棄してしまった場合、その他バイナリログの不整合(たとえばMulti-AZ設定のマスタのフェイルオーバを原因とした)などが発生した場合に発生する可能性があります。

以下は、リードレプリカでIOエラーが発生しているときの、"SHOW SLAVE STATUS"の出力一部。

mysql> show slave status\G
*************************** 1. row ***************************
           Slave_IO_State:
          Master_Log_File: mysql-bin-changelog.012345
    Relay_Master_Log_File: mysql-bin-changelog.012345
            Last_IO_Errno: 1236
            Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position; the first event 'mysql-bin-changelog.013406' at 1219393, the last event read from '/rdsdbdata/log/binlog/mysql-bin-changelog.012345' at 4, the last byte read from '/rdsdbdata/log/binlog/mysql-bin-changelog.012345' at 4.'
応急処置

レプリケーションマスタのログ位置を、マスタ上にある次のバイナリログの開始位置に変更します。これには、"mysql.rds_next_master_log"手続きが使えます。

CALL mysql.rds_next_master_log(curr_master_log);

mysqlでいう`CHANGE MASTER TO`構文にあたります

mysql> show slave status\G
*************************** 1. row ***************************
           Slave_IO_State:
          Master_Log_File: mysql-bin-changelog.012345
    Relay_Master_Log_File: mysql-bin-changelog.012345
            Last_IO_Errno: 1236
            Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position; the first event 'mysql-bin-changelog.013406' at 1219393, the last event read from '/rdsdbdata/log/binlog/mysql-bin-changelog.012345' at 4, the last byte read from '/rdsdbdata/log/binlog/mysql-bin-changelog.012345' at 4.'
mysql> call mysql.rds_next_master_log(12345);

+-------------------------------------+
| Message                             |
+-------------------------------------+
| Statement in error has been skipped |
+-------------------------------------+
1 row in set (0.01 sec)

+---------------------------+
| Message                   |
+---------------------------+
| Slave is running normally |
+---------------------------+
1 row in set (2.01 sec)
mysql> show slave status\G

参考:

予防

1. バイナリログを同期する

sync_binlog =1
innodb_support_xa=1
innodb_flush_logs_at_trx_commit=1

2. レプリケーションエラーが発生しうる作業のときだけレプリケーションを一時的に止める

call mysql.rds_start_replacation;
call mysql.rds_stop_replication;

参考:

その他のレプリケーションエラーの場合

たとえば、リードレプリカを新しく作り直す。


!



まとめ

  • レプリケーションIOエラー 1062,1236 エラーについてと、その応急処置、予防
  • レプリケーションエラーが発生するとレプリケーションは停止しますが、その原因のIOスレッドもしくはSQLスレッドの問題を解消すればレプリケーションは再開します
  • 一番ツヨいのはリードレプリカを新しく作り直す💪

© karahiyo