MySQL には、GTID ベースのレプリケーションで使用する組込み (ネイティブ) 関数がいくつか含まれています。 これらの関数は次のとおりです:
-
GTID_SUBSET(
set1
,set2
) グローバルトランザクション識別子
set1
およびset2
の 2 つのセットが指定されている場合、set1
内のすべての GTID もset2
内にあると true を返します。 それ以外の場合は、false を返します。-
GTID_SUBTRACT(
set1
,set2
) グローバルトランザクション識別子
set1
およびset2
の 2 つのセットがある場合、set2
にない GTID のみをset1
から返します。-
WAIT_FOR_EXECUTED_GTID_SET(
gtid_set
[,timeout
]) サーバーが、グローバルトランザクション識別子が
gtid_set
に含まれているすべてのトランザクションを適用するまで待機します。 オプションのタイムアウトは、指定された秒数が経過すると、関数の待機を停止します。
これらの関数の詳細は、セクション12.19「グローバルトランザクション識別子 (GTID) で使用される機能」 を参照してください。
GTID を操作する独自のストアドファンクションを定義できます。 ストアドファンクションの定義の詳細は、第25章「ストアドオブジェクト」 を参照してください。 次の例は、組込みの GTID_SUBSET()
および GTID_SUBTRACT()
関数に基づいて作成できる便利なストアドファンクションを示しています。
これらのストアドファンクションでは、次のように delimiter コマンドを使用して MySQL ステートメントデリミタを縦棒に変更しています:
mysql> delimiter |
これらの関数はすべて GTID セットの文字列表現を引数として取るため、GTID セットと一緒に使用する場合は常に引用符で囲む必要があります。
この関数は、2 つの GTID セットが同じセットである場合、同じ方法で書式設定されていなくても、ゼロ以外 (true) を返します。
CREATE FUNCTION GTID_IS_EQUAL(gtid_set_1 LONGTEXT, gtid_set_2 LONGTEXT)
RETURNS INT
RETURN GTID_SUBSET(gtid_set_1, gtid_set_2) AND GTID_SUBSET(gtid_set_2, gtid_set_1)|
この関数は、2 つの GTID セットが非結合の場合、ゼロ以外 (true) を返します。
CREATE FUNCTION GTID_IS_DISJOINT(gtid_set_1 LONGTEXT, gtid_set_2 LONGTEXT)
RETURNS INT
RETURN GTID_SUBSET(gtid_set_1, GTID_SUBTRACT(gtid_set_1, gtid_set_2))|
この関数は、2 つの GTID セットが非結合で、sum
が 2 つのセットの和集合である場合、ゼロ以外 (true) を返します。
CREATE FUNCTION GTID_IS_DISJOINT_UNION(gtid_set_1 LONGTEXT, gtid_set_2 LONGTEXT, sum LONGTEXT)
RETURNS INT
RETURN GTID_IS_EQUAL(GTID_SUBTRACT(sum, gtid_set_1), gtid_set_2) AND
GTID_IS_EQUAL(GTID_SUBTRACT(sum, gtid_set_2), gtid_set_1)|
この関数は、GTID セットの正規化された形式をすべて大文字で返します。空白はなく、重複もありません。 UUID はアルファベット順に配置され、間隔は数値順に配置されます。
CREATE FUNCTION GTID_NORMALIZE(g LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(g, '')|
この関数は、2 つの GTID セットの和集合を返します。
CREATE FUNCTION GTID_UNION(gtid_set_1 LONGTEXT, gtid_set_2 LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_NORMALIZE(CONCAT(gtid_set_1, ',', gtid_set_2))|
この関数は、2 つの GTID セットの交差を返します。
CREATE FUNCTION GTID_INTERSECTION(gtid_set_1 LONGTEXT, gtid_set_2 LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(gtid_set_1, GTID_SUBTRACT(gtid_set_1, gtid_set_2))|
この関数は、2 つの GTID セット (gtid_set_1
には存在するが gtid_set_2
には存在しない GTID) と、gtid_set_2
には存在するが gtid_set_1
には存在しない GTID の対称差異を戻します。
CREATE FUNCTION GTID_SYMMETRIC_DIFFERENCE(gtid_set_1 LONGTEXT, gtid_set_2 LONGTEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(CONCAT(gtid_set_1, ',', gtid_set_2), GTID_INTERSECTION(gtid_set_1, gtid_set_2))|
この関数は GTID セットから、指定された起点からすべての GTID を削除し、残りの GTID があればそれを返します。 UUID は、トランザクションが発生したサーバーで使用される識別子で、通常は server_uuid
値です。
CREATE FUNCTION GTID_SUBTRACT_UUID(gtid_set LONGTEXT, uuid TEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(gtid_set, CONCAT(UUID, ':1-', (1 << 63) - 2))|
この関数は、指定された識別子 (UUID) を持つサーバーから発生した GTID セットの GTID のみを返すように、以前に一覧表示された関数を逆にします。
CREATE FUNCTION GTID_INTERSECTION_WITH_UUID(gtid_set LONGTEXT, uuid TEXT)
RETURNS LONGTEXT
RETURN GTID_SUBTRACT(gtid_set, GTID_SUBTRACT_UUID(gtid_set, uuid))|
例 17.1 レプリカが最新であることの確認
組込み関数 GTID_SUBSET
および GTID_SUBTRACT
を使用すると、ソースが適用したすべてのトランザクションにレプリカが適用されているかどうかを確認できます。
GTID_SUBSET
でこのチェックを実行するには、レプリカで次のステートメントを実行します:
SELECT GTID_SUBSET(source_gtid_executed, replica_gtid_executed)
これが 0 (false) を返す場合、source_gtid_executed
の GTID の一部が replica_gtid_executed
に存在しないため、レプリカが適用されていないトランザクションがソースによって適用されているため、レプリカは最新ではありません。
GTID_SUBTRACT
でチェックを実行するには、レプリカで次のステートメントを実行します:
SELECT GTID_SUBTRACT(source_gtid_executed, replica_gtid_executed)
このステートメントは、source_gtid_executed
にはあるが replica_gtid_executed
にはない GTID を返します。 GTID が返された場合、ソースはレプリカが適用していない一部のトランザクションを適用しているため、レプリカは最新ではありません。
例 17.2 バックアップおよびリストアのシナリオ
ストアドファンクション GTID_IS_EQUAL
、GTID_IS_DISJOINT
および GTID_IS_DISJOINT_UNION
を使用して、複数のデータベースおよびサーバーに関連するバックアップおよびリストア操作を検証できます。 この例のシナリオでは、server1
にデータベース db1
が含まれ、server2
にデータベース db2
が含まれています。 目的は、データベース db2
を server1
にコピーし、server1
での結果を 2 つのデータベースの和集合にすることです。 使用する手順は、mysqlpump または mysqldump を使用して server2
をバックアップし、server1
でこのバックアップをリストアすることです。
バックアッププログラムオプション --set-gtid-purged
が ON
に設定されているか、AUTO
のデフォルトに設定されている場合、プログラム出力には SET @@GLOBAL.gtid_purged
ステートメントが含まれ、gtid_executed
セットを server2
から server1
の gtid_purged
に追加します。 gtid_purged
セットには、サーバー上でコミットされたが、サーバー上のバイナリログファイルに存在しないすべてのトランザクションの GTID が含まれています。 データベース db2
を server1
にコピーする場合、server1
のバイナリログファイルにない server2
でコミットされたトランザクションの GTID を server1
の gtid_purged
セットに追加して、セットを完成させる必要があります。
ストアドファンクションを使用すると、このシナリオの次のステップを実行できます:
-
GTID_IS_EQUAL
を使用して、バックアップ操作によってSET @@GLOBAL.gtid_purged
ステートメントの正しい GTID セットが計算されたことを確認します。server2
では、mysqlpump または mysqldump の出力からそのステートメントを抽出し、GTID セットを$gtid_purged_set
などのローカル変数に格納します。 次に、次のステートメントを実行します:server2> SELECT GTID_IS_EQUAL($gtid_purged_set, @@GLOBAL.gtid_executed);
結果が 1 の場合、2 つの GTID セットは等しく、セットは正しく計算されています。
-
GTID_IS_DISJOINT
を使用して、mysqlpump または mysqldump 出力の GTID セットがserver1
のgtid_executed
セットと重複していないことを確認します。 両方のサーバーに同一の GTID が存在すると、データベースdb2
をserver1
にコピーするときにエラーが発生します。 確認するには、server1
で、前述のように出力からgtid_purged
セットを抽出してローカル変数に格納し、次のステートメントを実行します:server1> SELECT GTID_IS_DISJOINT($gtid_purged_set, @@GLOBAL.gtid_executed);
結果が 1 の場合、2 つの GTID セット間に重複がないため、重複する GTID は存在しません。
-
GTID_IS_DISJOINT_UNION
を使用して、リストア操作がserver1
で正しい GTID 状態になったことを確認します。 バックアップをリストアする前に、server1
で次のステートメントを実行して既存のgtid_executed
セットを取得します:server1> SELECT @@GLOBAL.gtid_executed;
結果をローカル変数
$original_gtid_executed
に格納します。 また、前述のように、gtid_purged
セットをローカル変数に格納します。server2
からのバックアップがserver1
にリストアされたら、次のステートメントを実行して GTID 状態を確認します:server1> SELECT GTID_IS_DISJOINT_UNION($original_gtid_executed, $gtid_purged_set, @@GLOBAL.gtid_executed);
結果が 1 の場合、ストアドファンクションは、
server1
($original_gtid_executed
) からの元のgtid_executed
セットとserver2
($gtid_purged_set
) から追加されたgtid_purged
セットが重複していないことを検証し、server1
で更新されたgtid_executed
セットが、server1
からの以前のgtid_executed
セットとserver2
からのgtid_purged
セットで構成されるようになりました。これが目的の結果です。server1
でこれ以上のトランザクションが実行される前に、このチェックが実行されていることを確認してください。実行されていない場合、gtid_executed
セットの新しいトランザクションが失敗します。
例 17.3 手動フェイルオーバー用の最新レプリカの選択
ストアドファンクション GTID_UNION
を使用すると、ソースサーバーが予期せず停止した後に手動フェイルオーバー操作を実行するために、レプリカのセットから最新のレプリカを識別できます。 一部のレプリカでレプリケーションラグが発生している場合、このストアドファンクションを使用すると、すべてのレプリカが既存のリレーログを適用するのを待機せずに最新のレプリカを計算できるため、フェイルオーバー時間を最小限に抑えることができます。 この関数は、「パフォーマンススキーマ」テーブル replication_connection_status
に記録されているレプリカが受信したトランザクションのセットを使用して、各レプリカの gtid_executed
セットの和集合を戻すことができます。 これらの結果を比較して、すべてのトランザクションがまだコミットされていない場合でも、最新のトランザクションのレプリカレコードを検索できます。
各レプリカで、次のステートメントを発行してトランザクションの完全なレコードを計算します:
SELECT GTID_UNION(RECEIVED_TRANSACTION_SET, @@GLOBAL.gtid_executed)
FROM performance_schema.replication_connection_status
WHERE channel_name = 'name';
その後、各レプリカの結果を比較してトランザクションの最新レコードを確認し、このレプリカを新しいソースとして使用できます。
例 17.4 レプリカ上の無関係なトランザクションのチェック
ストアドファンクション GTID_SUBTRACT_UUID
を使用すると、指定されたソースから発生しなかったトランザクションをレプリカが受信したかどうかを確認できます。 その場合は、レプリケーションの設定、またはプロキシ、ルーターまたはロードバランサに問題がある可能性があります。 この機能は、GTID セットから指定された発信元サーバーからすべての GTID を削除し、残りの GTID があればそれを返すことによって機能します。
単一のソースからレプリケートするレプリカの場合、次のステートメントを発行し、元のソースの識別子 (通常は server_uuid
値) を指定します:
SELECT GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed, server_uuid_of_source);
結果が空でない場合、返されるトランザクションは、指定されたソースから発生しなかった余分なトランザクションです。
マルチソースレプリケーショントポロジのレプリカの場合は、次の例のように機能を繰り返します:
SELECT GTID_SUBTRACT_UUID(GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed,
server_uuid_of_source_1),
server_uuid_of_source_2);
結果が空でない場合、返されるトランザクションは、指定されたどのソースからも発生しなかった余分なトランザクションです。
例 17.5 レプリケーショントポロジ内のサーバーが読取り専用であることの確認
ストアドファンクション GTID_INTERSECTION_WITH_UUID
を使用すると、サーバーが GTID を発生させておらず、読取り専用状態であることを検証できます。 この関数は、指定された識別子を持つサーバーから発生した GTID セットから GTID のみを返します。 サーバー gtid_executed
セット内のいずれかのトランザクションにサーバー独自の識別子がある場合、サーバー自体がそれらのトランザクションを開始しています。 サーバーで次のステートメントを発行して確認できます:
SELECT GTID_INTERSECTION_WITH_UUID(@@GLOBAL.gtid_executed, my_server_uuid);
例 17.6 マルチソースレプリケーション設定での追加レプリカの検証
ストアドファンクション GTID_INTERSECTION_WITH_UUID
を使用すると、マルチソースレプリケーション設定にアタッチされたレプリカが、特定のソースから発生したすべてのトランザクションを適用したかどうかを確認できます。 このシナリオでは、source1
と source2
の両方がソースとレプリカであり、相互にレプリケートされます。source2
には、独自のレプリカもあります。 また、source2
が log_slave_updates=ON
で構成されている場合、レプリカはソース source1
からトランザクションを受信して適用しますが、source2
が log_slave_updates=OFF
を使用している場合は行いません。 いずれの場合も、現在、レプリカが source2
で最新であるかどうかのみを確認します。 この状況では、ストアドファンクション GTID_INTERSECTION_WITH_UUID
を使用して、source2
が発生させたトランザクションを識別し、source2
が source1
からレプリケートしたトランザクションを破棄できます。 その後、組込み関数 GTID_SUBSET
を使用して、結果をレプリカ上の gtid_executed
セットと比較できます。 レプリカが source2
で最新の場合、レプリカに設定されている gtid_executed
には交差セット (source2
から発生したトランザクション) 内のすべてのトランザクションが含まれます。
このチェックを実行するには、次のように、source2
の gtid_executed
セット、source2
のサーバー UUID およびレプリカ gtid_executed
セットをクライアント側の変数に格納します:
$source2_gtid_executed :=
source2> SELECT @@GLOBAL.gtid_executed;
$source2_server_uuid :=
source2> SELECT @@GLOBAL.server_uuid;
$replica_gtid_executed :=
replica> SELECT @@GLOBAL.gtid_executed;
次に、次のように、これらの変数を入力として GTID_INTERSECTION_WITH_UUID
および GTID_SUBSET
を使用します:
SELECT GTID_SUBSET(GTID_INTERSECTION_WITH_UUID($source2_gtid_executed,
$source2_server_uuid),
$replica_gtid_executed);
source2
($source2_server_uuid
) のサーバー識別子は、source1
で発生した GTID を除外して、source2
の gtid_executed
セットからの GTID のみを識別して返すために GTID_INTERSECTION_WITH_UUID
とともに使用されます。 結果の GTID セットは、GTID_SUBSET
を使用して、レプリカで実行されたすべての GTID のセットと比較されます。 このステートメントがゼロ以外 (true) を返す場合、source2
から識別された GTID (最初のセット入力) もすべてレプリカ gtid_executed
セット (2 番目のセット入力) に含まれます。つまり、レプリカは source2
から発生したすべてのトランザクションをレプリケートしています。