はじめに
去年のブログ記事でも触れましたが、現在のGaleraライブラリの最新バージョンは 4.0 系です。
去年の時点では 4.0 系はMariaDBにのみ実装されていましたが、今年GAになったPercona XtraDB Cluster 8.0(以下、PXC8.0)にも Galera 4.0 は組み込まれています。
そこで、この記事ではまだ本ブログで説明していなかったGalera 4.0の新機能のうち、「Synchronization Functions」と「Galera System Tables」の説明をしたいと思います。
Synchronization Functions
Synchronization Functionsは、galera 4.0 から導入された関数です。これらは全てGTIDを操作するための関数です。
ここでいうGTIDは、MySQLのGTIDではなく、GaleraのGTIDのことを指します。ただ、GaleraのGTIDもクラスタグループを識別する「UUID」と更新クエリの実行順である「シーケンス番号」の組み合わせでできており、クラスタに参加している各ノードがどの時点まで同期されているかを示したものなので、役割に余り違いはありません。
Synchronization Functionsとして実装された関数は以下の3つです。それぞれの役割について解説します。
- WSREP_LAST_SEEN_GTID()
- WSREP_LAST_WRITTEN_GTID()
- WSREP_SYNC_WAIT_UPTO_GTID()
WSREP_LAST_SEEN_GTID()
MySQLでいうLAST_INSERT_ID()関数のように、クライアントから見た最後(最新)のGTIDを返す関数です。引数の指定は不要で、以下のクエリで情報を取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
node1> CREATE DATABASE d1; node1> CREATE TABLE d1.t1 (id INT primary key); node1> START TRANSACTION; node1> INSERT d1.t1 VALUES (1); node1> COMMIT; node1> SELECT WSREP_LAST_SEEN_GTID(); +-----------------------------------------+ | WSREP_LAST_SEEN_GTID() | +-----------------------------------------+ | aca35fd7-ddd4-11ea-8720-fe99a0ebf69f:39 | +-----------------------------------------+ 1 row in set (0.00 sec) ### Node2に切替 node2> SELECT WSREP_LAST_SEEN_GTID(); +-----------------------------------------+ | WSREP_LAST_SEEN_GTID() | +-----------------------------------------+ | aca35fd7-ddd4-11ea-8720-fe99a0ebf69f:39 | +-----------------------------------------+ 1 row in set (0.00 sec) |
この関数は、後述する WSREP_SYNC_WAIT_UPTO_GTID() と組み合わせて使用すると便利です。このパラメータを使用して、クライアントのブロックを解除する前に待機すべきトランザクションを判断することができます。
ちなみに、PXC8.0.19では以下のバグがあり、GTIDではなく不正な値が出力されてしまいます。そのため、同バージョンでは余りこれらの関数を使用しない方が良いかと思います。
https://jira.percona.com/browse/PXC-3381
1 2 3 4 5 6 7 |
node1> SELECT WSREP_LAST_SEEN_GTID(); +----------------------------------------------------------------------------------+ | WSREP_LAST_SEEN_GTID() | +----------------------------------------------------------------------------------+ | 0x32383163663637642D646431632D313165612D616633642D6136353466323536626530633A3338 | +----------------------------------------------------------------------------------+ 1 row in set (0.00 sec) |
WSREP_LAST_WRITTEN_GTID()
この関数は、クライアントが実行した最後の更新クエリのGTIDを返します。これも、後述するWSREP_SYNC_WAIT_UPTO_GTID() と組み合わせて使用すると便利です。このパラメータを使用して、クライアントのブロックを解除する前に待機すべきトランザクションを特定することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
node1> SELECT WSREP_LAST_WRITTEN_GTID(); +-----------------------------------------+ | WSREP_LAST_WRITTEN_GTID() | +-----------------------------------------+ | aca35fd7-ddd4-11ea-8720-fe99a0ebf69f:39 | +-----------------------------------------+ 1 row in set (0.00 sec) ### Node2に切替 node2> SELECT WSREP_LAST_WRITTEN_GTID(); +-----------------------------------------+ | WSREP_LAST_WRITTEN_GTID() | +-----------------------------------------+ | 00000000-0000-0000-0000-000000000000:-1 | +-----------------------------------------+ 1 row in set (0.00 sec) |
上記の通り、更新トランザクションを実行していないノードでは WSREP_LAST_WRITTEN_GTID()関数の返り値は初期値のままになっています。
WSREP_SYNC_WAIT_UPTO_GTID()
この関数は、引数に指定されたGTIDのトランザクションが適用され、コミットが完了するまで、他クライアントの処理をブロックします。引数にはタイムアウトする秒数を指定することもできます。タイムアウト値を指定しない場合は、無期限にブロックし続けます。関数の返り値としては以下の3パターンがあります。
1 2 3 4 5 6 7 8 |
1: ノードは指定されたグローバル・トランザクション ID を適用し、コミットしました ER_LOCAL_WAIT_TIMEOUT: ノードがトランザクションを適用する前に関数がタイムアウトしたエラーです ER_WRONG_ARGUMENTS: 関数には不正なグローバル・トランザクション ID が与えられているエラーです |
例えば以下のような使い方をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# Node1 で巨大かつ大量のトランザクションを実行する node1> SELECT WSREP_LAST_SEEN_GTID(); +-----------------------------------------+ | WSREP_LAST_SEEN_GTID() | +-----------------------------------------+ | aca35fd7-ddd4-11ea-8720-fe99a0ebf69f:40 | +-----------------------------------------+ node2> SELECT WSREP_LAST_SEEN_GTID(); +-----------------------------------------+ | WSREP_LAST_SEEN_GTID() | +-----------------------------------------+ | aca35fd7-ddd4-11ea-8720-fe99a0ebf69f:20 | +-----------------------------------------+ # Node2 でWrite-Set処理が遅延していることが分かる # Node1 の最新のGTIDまでNode2の処理を停止する node2> SELECT WSREP_SYNC_WAIT_UPTO_GTID("aca35fd7-ddd4-11ea-8720-fe99a0ebf69f:40"); |
イメージとしては、Galeraの「Flow Control」を任意のタイミングで手動実行できるというイメージです。意図しないノード間同期の遅延の解消などが期待できるので、Galera運用者として出来ることが増えると考えられます。
Galera System Tables
galera 4.0 から、mysqlデータベースに以下3つのシステムテーブルが追加されました。
- wsrep_cluster
- wsrep_cluster_members
- wsrep_streaming_log
これらテーブルは、データベース管理者がクラスタ内のノードの現在のレイアウトを把握するために使用することができます。また、テーブルは参照専用となっており更新はできません。
wsrep_cluster
このテーブルには、最新のクラスタのビュー情報が格納されています。具体的には、クラスタのUUIDとその他の識別情報が格納されています。例えば以下のような情報です。
1 2 3 4 5 6 7 8 |
node1> SELECT * FROM mysql.wsrep_cluster\G *************************** 1. row *************************** cluster_uuid: 281cf67d-dd1c-11ea-af3d-a654f256be0c view_id: 3 view_seqno: 36 protocol_version: 4 capabilities: 184703 1 row in set (0.00 sec) |
cluster_uuid カラムには、クラスタのUUIDが入っています。
view_id は、 wsrep_cluster_conf_id のステータス値に対応し、クラスタ構成が変更された回数を表します。
一方、view_seqno は、クラスタビューに関連付けられたGaleraシーケンス番号に対応します。
protocol_version は、wsrep_protocol_version変数に含まれる値と同じです。MySQL-wsrepまたはMariaDB wsrepパッチのプロトコルバージョンです。
最後に、capabilitiesカラムにはGaleraライブラリによって提供されるcapabilitiesビットマスクが含まれています。これは、クラッシュ回復時にノードの状態を回復するために必要となるメタデータです。
wsrep_cluster_members
このテーブルは、クラスタに所属する現在のメンバーの情報が格納されています。つまりテーブルを参照したノードが把握している全Galeraノードの情報が含まれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
node1> SELECT * FROM mysql.wsrep_cluster_members\G *************************** 1. row *************************** node_uuid: 280b48b4-dd1c-11ea-9e85-ee570045d48e cluster_uuid: 281cf67d-dd1c-11ea-af3d-a654f256be0c node_name: node1 node_incoming_address: 127.0.0.1:27920 *************************** 2. row *************************** node_uuid: 379faa66-dd1c-11ea-b83a-f70538b20e69 cluster_uuid: 281cf67d-dd1c-11ea-af3d-a654f256be0c node_name: node2 node_incoming_address: 127.0.0.1:27921 *************************** 3. row *************************** node_uuid: 58661908-dd1c-11ea-9470-824bdc0157e8 cluster_uuid: 281cf67d-dd1c-11ea-af3d-a654f256be0c node_name: node3 node_incoming_address: 127.0.0.1:27922 3 rows in set (0.00 sec) |
node_uuidはクラスタ内の各ノードのUUIDを記録します。
cluster_uuidは、ノードが属するクラスタのUUIDです。これは現在 wsrep_cluster テーブルに含まれているものと同じです。
node_nameには各ノードの名称(wsrep_node_name変数)が入っています。
最後に、node_incoming_addressには各ノードがクライアント接続をLISTENしているIPアドレスとポートが格納されます。
wsrep_streaming_log
このテーブルは Streaming Replicationに関するもので、進行中のストリーミングトランザクションのメタデータと行イベント、行ごとのWrite-Setフラグメントが含まれています。Streaming Replicationについては、この記事を参照してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
node1> CREATE TABLE d1.t2 (col1 INT PRIMARY KEY); node1> SET SESSION wsrep_trx_fragment_size=1; node1> START TRANSACTION; node1> INSERT INTO d1.t2 VALUES (100); node1> SELECT node_uuid, trx_id, seqno, flags FROM mysql.wsrep_streaming_log; +--------------------------------------+--------+-------+-------+ | node_uuid | trx_id | seqno | flags | +--------------------------------------+--------+-------+-------+ | e07aa53b-ddcc-11ea-aaf7-433818d75b99 | 133 | 39 | 1 | +--------------------------------------+--------+-------+-------+ 1 row in set (0.00 sec) ※結果が長くなるためfrag列は含めていません node1> COMMIT; node1> SELECT node_uuid, trx_id, seqno, flags FROM mysql.wsrep_streaming_log; Empty set (0.00 sec) |
node_uuid カラムには、トランザクションのホストノード(すなわち、クライアントがトランザクションを実行しているノード)のノードUUIDが入っています。
trx_id カラムにはトランザクション識別子を格納され、seqno カラムにはWrite-Setフラグメントのシーケンス番号が格納されています。
最後に、flags カラムには Write-Set フラグメントに関連付けられたフラグを記録し、frag は Write-Set フラグメントに含まれるバイナリログレプリケーションイベントが格納されています。
wsrep_streaming_log テーブルはレプリケーション中の情報を格納しているため、何も更新トランザクション(Write-Set)が存在しないときは empty になっています。レプリケーションのハングアップなど問題が発生した場合に参照するのが良いでしょう。
おわりに
galera4ライブラリでは、Galeraレプリケーションの性能が改善したことに加えて操作性も向上しました。主要なGalera製品であるMariaDB Galera ClusterおよびPXCにも実装され、今後一層良いクラスタ製品になっていくことに期待したいです。