MySQL道普請便り

第212回MySQLレプリケーション関連の便利なビルトイン関数

今回は、知っておくと得するかもしれないレプリケーション関連で使用できるビルトイン関数について紹介したいと思います。GTIDとポジションレプリケーションで使用できる関数を重点的に説明します。

GTIDレプリケーション関連のビルトイン関数

ここではGTIDレプリケーション環境で利用できるビルトイン関数を紹介します。

GTID_SUBSET()関数

GTID_SUBSET(*gtid_set1*,*gtid_set2*)関数は、引数に2つのGTIDセットをとります。指定したGTIDセットを比較して差異を調べることができ、gtid_set1内のすべてのGTIDがgtid_set2内にあるとtrueを返します。それ以外の場合はfalseを返します。

mysql> SELECT GTID_SUBSET(
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25',
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25') as subset;
+--------+
| subset |
+--------+
|      1 |
+--------+
1 row in set (0.00 sec)

mysql> SELECT GTID_SUBSET(
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25',
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-26') as subset;
+--------+
| subset |
+--------+
|      1 |
+--------+
1 row in set (0.00 sec)


mysql> SELECT GTID_SUBSET(
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-26',
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25') as subset;
+--------+
| subset |
+--------+
|      0 |
+--------+
1 row in set (0.00 sec)

また、異なるサーバーから発生したGTIDを含めたGTIDセットの比較も可能です。

mysql> SELECT GTID_SUBSET(
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb:1-3',
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-30,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb:1-10') as subset;
+--------+
| subset |
+--------+
|      1 |
+--------+
1 row in set (0.00 sec)

この関数の使いどころとしては、以下のようなケースが挙げられます。

  • ソースとレプリカの不整合チェック
  • フェールオーバー時における昇格レプリカ選定

ソースとレプリカの不整合チェックでは、ソースで適用されたGTIDセットはかならずレプリカに適用されていなくてはいけません。レプリカのみに適用されたGTIDが存在する場合はなにかしらの更新がレプリカにあったと考えられるので、データの不整合がおこっている可能性があります。そのため、この関数を利用して差異がないかチェックすることは重要です。このあと紹介するGTID_SUBTRACT()関数を使って過不足のGTIDを特定することもできます。

フェールオーバー時における昇格レプリカ選定というのは、複数のレプリカをもつソースがダウンしたら、その複数のレプリカから1つをソースへ昇格する必要があるとします。その際に、より最新のGTIDセットをもったレプリカを昇格される必要があり、その比較のために利用できます。

GTID_SUBTRACT()関数

GTID_SUBTRACT(*gtid_set1*,*gtid_set2*)関数は、引数に2つのGTIDセットをとります。指定したGTIDセットを比較して差異を調べることができ、gtid_set1に含まれるGTIDの内、gtid_set2に含まれないものを返します。gtid_set2にすべて含まれていると、空の値を返します。

mysql> SELECT GTID_SUBTRACT(
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-27',  
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25') as subtract;
+--------------------------------------------+
| subtract                                   |
+--------------------------------------------+
| aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:26-27 |
+--------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT GTID_SUBTRACT(
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25',  
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-25') as subtract;
+----------+
| subtract |
+----------+
|          |
+----------+
1 row in set (0.00 sec)

WAIT_FOR_EXECUTED_GTID_SET()関数

WAIT_FOR_EXECUTED_GTID_SET(*gtid_set*[,*timeout*])関数は、第1引数にGTIDセットを指定し、第2引数にタイムアウト値を指定します。この関数は、引数に指定したGTIDセットに含まれているすべてのトランザクションがMySQLサーバに適用されるまで待機します。第2引数を指定しない場合はタイムアウトはデフォルト値の0が設定されます。この場合、GTIDセット内のすべてのトランザクションが適用されるまで、関数は常に待機します。

mysql> SELECT WAIT_FOR_EXECUTED_GTID_SET(
    -> 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-55150206,
    ->  bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb:1-25635169') as WAIT_FOR_EXECUTED_GTID_SET;
+----------------------------+
| WAIT_FOR_EXECUTED_GTID_SET |
+----------------------------+
|                          0 |
+----------------------------+
1 row in set (36.41 sec)

戻り値の0は成功を表し、1はタイムアウトを表します。

こちらの関数の使いどころを考えます。たとえば、レプリケーション遅延による古いデータの読み取りが許容されない環境下にて、リードレプリカへ問い合わせするときに利用できると思います。ソースに更新した際にgtid_executed変数の値を取得、保持しておき、リードレプリカにその更新が完了されたことを、この関数を利用し確認したあとにSELECTをするという方法があります。処理が遅くなるためおすすめはしませんが、このような利用方法はあると思います。

WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()関数

こちらの関数は非推奨であり、WAIT_FOR_EXECUTED_GTID_SET()関数の利用を推奨されています。そのため説明は省きます。

ポジションレプリケーション関連のビルトイン関数

ここではポジションレプリケーション環境で利用できるビルトイン関数を紹介します。

SOURCE_POS_WAIT()関数

SOURCE_POS_WAIT(*log_file*,*log_pos*[,*timeout*][,*channel*])関数は、第1引数にソースバイナリログファイル名を指定し、第2引数にソースのバイナルログのポジションを指定します。

この関数は、レプリカがソースのバイナリログ内の指定されたポジションまでのすべての更新を読み取って適用するまでブロックします。先ほど説明したWAIT_FOR_EXECUTED_GTID_SET()のポジションレプリケーション用の関数です。MySQL 5.7とそれ以前ではMASTER_POS_WAIT()という関数名でした。第3引数はタイムアウト値で、第4引数はレプリケーションチャネル名をとります。タイムアウト値を指定しない場合は無限に待機します。レプリケーションチャネル名を指定しない場合は、空の文字列("")であるデフォルトチャネルが設定されます。

mysql> SELECT SOURCE_POS_WAIT('mysql-bin.000044',84805737);
+-----------------------------------------------+
| MASTER_POS_WAIT('mysql-bin.000044',84805737)  |
+-----------------------------------------------+
|                                           301 |
+-----------------------------------------------+
1 row in set (18.02 sec)

戻り値は、レプリカが指定されたポジションに進むまでに待機する必要があったログイベントの数です。

また、この関数はステートメントベースのレプリケーションでは安全に使用できません。 binlog_formatがSTATEMENTに設定されているときにこの関数を使用すると、警告のログが記録されます。

非同期レプリケーションのフェールオーバー関連のビルトイン関数

非同期レプリケーションのフェールオーバーによる自動ソース切り替えを行う関数には以下のものがあります。

  • asynchronous_connection_failover_add_managed()関数
  • asynchronous_connection_failover_add_source()関数
  • asynchronous_connection_failover_delete_managed()関数
  • asynchronous_connection_failover_delete_source()関数
  • asynchronous_connection_failover_reset()関数

これらの関数と使い方は、第195回 MySQLレプリカの自動ソース切り替えにて紹介していますのでご確認ください。

まとめ

今回はレプリケーション関連の便利なビルトイン関数について紹介しました。以下のドキュメントでは、これらの関数についてより詳しく説明していますので、あわせてご確認ください。

おすすめ記事

記事・ニュース一覧