最近、MariaDBレプリケーションのセットアップに関する興味深いカスタマーサポートの事例に遭遇しました。私たちはこの問題の調査に多くの時間を費やし、このブログ投稿でこれを共有する価値があると考えました。
問題は次のとおりです。古い(10.xより前の)MariaDBサーバーが使用されていて、そこからより新しいMariaDBレプリケーションセットアップにデータを移行しようとしました。これにより、Mariabackupを使用して新しいレプリケーションクラスターでスレーブを再構築する際に問題が発生しました。テストの目的で、次の環境でこの動作を再現しました。
データは、mysqldumpを使用して5.5から10.4に移行されました:
>mysqldump --single-transaction --master-data=2 --events --routines sbtest > /root/dump.sql
これにより、マスターバイナリログ座標と一貫性のあるダンプを収集できました。その結果、MariaDB 10.4マスターノードをプロビジョニングし、古い5.5マスターと新しい10.4ノード間のレプリケーションをセットアップすることができました。トラフィックはまだ5.5ノードで実行されていました。 10.4マスターは、データを10.4スレーブに複製する必要があるため、GTIDを生成していました。詳細を掘り下げる前に、MariaDBでGTIDがどのように機能するかを簡単に見てみましょう。
MariaDBとGTID
まず、MariaDBはOracleMySQLとは異なる形式のGTIDを使用します。ダッシュで区切られた3つの数字で構成されています:
0 --1 --345
1つ目はレプリケーションドメインであり、マルチソースレプリケーションを適切に処理できます。すべてのノードが同じレプリケーションドメインにあるため、これはこの場合には関係ありません。 2番目の番号は、GTIDを生成したノードのサーバーIDです。 3つ目はシーケンス番号です。これは、バイナリログに保存されるイベントごとに単調に増加します。
MariaDBはいくつかの変数を使用して、特定のノードで実行されたGTIDに関する情報を格納します。私たちにとって最も興味深いのは:
Gtid_binlog_pos-ドキュメントによると、この変数は、バイナリログに書き込まれた最後のイベントグループのGTIDです。
Gtid_slave_pos-ドキュメントによると、このシステム変数には、サーバーのスレーブスレッドによってデータベースに適用された最後のトランザクションのGTIDが含まれています。
Gtid_current_pos-ドキュメントによると、このシステム変数には、データベースに適用された最後のトランザクションのGTIDが含まれています。 gtid_binlog_posの対応するGTIDのserver_idがサーバー自身のserver_idと等しく、シーケンス番号がgtid_slave_posの対応するGTIDよりも大きい場合、gtid_binlog_posのGTIDが使用されます。それ以外の場合は、gtid_slave_posのGTIDがそのドメインに使用されます。
したがって、明確にするために、gtid_binlog_posは最後にローカルで実行されたイベントのGTIDを格納します。 Gtid_slave_posは、スレーブスレッドによって実行されたイベントのGTIDを格納し、gtid_current_posは、シーケンス番号が最も高く、server-idがある場合はgtid_binlog_posの値を示し、シーケンスが最も高い場合はgtid_slave_posを示します。これを覚えておいてください。
MariaDB [(none)]> show global variables like '%gtid%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| gtid_binlog_pos | 0-1001-1 |
| gtid_binlog_state | 0-1001-1 |
| gtid_cleanup_batch_size | 64 |
| gtid_current_pos | 0-1001-1 |
| gtid_domain_id | 0 |
| gtid_ignore_duplicates | ON |
| gtid_pos_auto_engines | |
| gtid_slave_pos | 0-1001-1 |
| gtid_strict_mode | ON |
| wsrep_gtid_domain_id | 0 |
| wsrep_gtid_mode | OFF |
+-------------------------+----------+
11 rows in set (0.001 sec)
gtid_slave_posに注意してください。これは理論的には意味がありません。同じノードからのものですが、スレーブスレッドを介したものです。これは、以前にマスタースイッチを作成した場合に発生する可能性があります。それを実行しました。2つの10.4ノードがあり、マスターをサーバーIDが1001のホストからサーバーIDが1002のホストに切り替えてから、1001に戻しました。
その後、レプリケーションを5.5から10.4に構成しました。これは、次のようになります。
MariaDB [(none)]> show global variables like '%gtid%';
+-------------------------+-------------------------+
| Variable_name | Value |
+-------------------------+-------------------------+
| gtid_binlog_pos | 0-55-117029 |
| gtid_binlog_state | 0-1001-1537,0-55-117029 |
| gtid_cleanup_batch_size | 64 |
| gtid_current_pos | 0-1001-1 |
| gtid_domain_id | 0 |
| gtid_ignore_duplicates | ON |
| gtid_pos_auto_engines | |
| gtid_slave_pos | 0-1001-1 |
| gtid_strict_mode | ON |
| wsrep_gtid_domain_id | 0 |
| wsrep_gtid_mode | OFF |
+-------------------------+-------------------------+
11 rows in set (0.000 sec)
ご覧のとおり、MariaDB 5.5から複製されたイベントは、すべてgtid_binlog_pos変数(サーバーIDが55のすべてのイベント)で考慮されています。これにより、重大な問題が発生します。覚えているかもしれませんが、gtid_binlog_posには、ホスト上でローカルに実行されるイベントが含まれている必要があります。ここには、異なるサーバーIDを持つ別のサーバーから複製されたイベントが含まれています。
これにより、10.4スレーブを再構築するときに問題が発生します。その理由は、次のとおりです。 Mariabackupは、Xtrabackupと同様に、簡単な方法で機能します。 REDOログをスキャンし、着信トランザクションを保存しながら、MariaDBサーバーからファイルをコピーします。ファイルがコピーされると、Mariabackupは、MariaDBのバージョンとバックアップロックの可用性に応じて、FLUSH TABLES WITHREADLOCKまたはバックアップロックのいずれかを使用してデータベースをフリーズします。次に、最後に実行されたGTIDを読み取り、バックアップと一緒に保存します。その後、ロックが解除され、バックアップが完了します。バックアップに保存されているGTIDは、ノードで最後に実行されたGTIDとして使用する必要があります。スレーブを再構築する場合は、gtid_slave_posとして配置され、GTIDレプリケーションを開始するために使用されます。このGTIDはgtid_current_posから取得されます。これは完全に理にかなっています。結局のところ、これは「データベースに適用された最後のトランザクションのGTID」です。急性の読者はすでに問題を見ることができます。 10.4が5.5マスターから複製されたときの変数の出力を示しましょう:
MariaDB [(none)]> show global variables like '%gtid%';
+-------------------------+-------------------------+
| Variable_name | Value |
+-------------------------+-------------------------+
| gtid_binlog_pos | 0-55-117029 |
| gtid_binlog_state | 0-1001-1537,0-55-117029 |
| gtid_cleanup_batch_size | 64 |
| gtid_current_pos | 0-1001-1 |
| gtid_domain_id | 0 |
| gtid_ignore_duplicates | ON |
| gtid_pos_auto_engines | |
| gtid_slave_pos | 0-1001-1 |
| gtid_strict_mode | ON |
| wsrep_gtid_domain_id | 0 |
| wsrep_gtid_mode | OFF |
+-------------------------+-------------------------+
11 rows in set (0.000 sec)
Gtid_current_posは0-1001-1に設定されています。これは間違いなく正しい瞬間ではありません。それはgtid_slave_posから取得されたものですが、その後5.5から発生した一連のトランザクションがあります。問題は、それらのトランザクションがgtid_binlog_posとして保存されることです。一方、gtid_current_posは、gtid_current_posとして使用する前にgitd_binlog_pos内のGTIDのローカルサーバーIDを必要とする方法で計算されます。この場合、それらは5.5ノードのサーバーIDを持っているため、10.4マスターで実行されたイベントとして適切に扱われません。バックアップの復元後、バックアップに保存されているGTIDの状態に従ってスレーブを設定すると、5.5から発生したすべてのイベントが再適用されることになります。これは明らかに、複製を壊します。
この問題の解決策は、いくつかの追加手順を実行することです。
- 5.5から10.4へのレプリケーションを停止します。 10.4マスターでSTOPSLAVEを実行します
- 10.4でトランザクションを実行します-存在しない場合はSCHEMAを作成しますバグ修正-これにより、GTIDの状況が次のように変更されます:
MariaDB [(none)]> show global variables like '%gtid%';
+-------------------------+---------------------------+
| Variable_name | Value |
+-------------------------+---------------------------+
| gtid_binlog_pos | 0-1001-117122 |
| gtid_binlog_state | 0-55-117121,0-1001-117122 |
| gtid_cleanup_batch_size | 64 |
| gtid_current_pos | 0-1001-117122 |
| gtid_domain_id | 0 |
| gtid_ignore_duplicates | ON |
| gtid_pos_auto_engines | |
| gtid_slave_pos | 0-1001-1 |
| gtid_strict_mode | ON |
| wsrep_gtid_domain_id | 0 |
| wsrep_gtid_mode | OFF |
+-------------------------+---------------------------+
11 rows in set (0.001 sec)
最新のGITDはローカルで実行されたため、gtid_binlog_posとして保存されました。ローカルサーバーIDを持っているため、gtid_current_posとして選択されます。これで、バックアップを取り、それを使用して10.4マスターからスレーブを再構築できます。これが完了したら、スレーブスレッドを再開します。
MariaDBは、この種のバグが存在することを認識しています。検出された関連するバグレポートの1つは、https://jira.mariadb.org/browse/MDEV-10279です。残念ながら、これまでのところ修正はありません。 。私たちが見つけたのは、この問題が5.5までのMariaDBに影響を与えるということです。 MariaDB 10.0からの非GTIDイベントは、スレーブスレッドからのイベントとして10.4で正しく考慮され、gtid_slave_posが適切に更新されます。 MariaDB 5.5はかなり古いものです(まだサポートされていますが)ので、セットアップが実行されているのを確認し、5.5からより新しいGTID対応のMariaDBバージョンに移行しようとする場合があります。さらに悪いことに、私たちが見つけたバグレポートによると、これは非MariaDB(コメントの1つはPercona Server 5.6に表示される問題に言及しています)サーバーからMariaDBへのレプリケーションにも影響します。
とにかく、このブログ投稿がお役に立てば幸いです。また、今説明した問題に遭遇しないことを願っています。