はじめに
Galera ClusterでrsyncでSSTをしているみなさんこんにちは。
State Snapshot Transfers — Galera Cluster Documentation
公式ドキュメントによると、rsyncはdonorノードがblockingになるとあります。
本当?
ということで実験です。
環境
5.5.45、3台構成。
# mysql -uroot -e "show status like 'wsrep_cluster%';"
+--------------------------+--------------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------------+
| wsrep_cluster_conf_id | 14 |
| wsrep_cluster_size | 3 |
| wsrep_cluster_state_uuid | cf819ec9-e382-11e7-a390-768e47ae6c01 |
| wsrep_cluster_status | Primary |
+--------------------------+--------------------------------------+
SSTの発生方法
1台をサービス停止。そのノードのgrastate.datを削除して起動すると、SSTになります。
その理由はこちらを確認してください。
Node Provisioning — Galera Cluster Documentation
When a node joins the cluster, it compares its own state UUID to that of the Primary Component. If the state UUID does not match, the joining node requests a state transfer from the cluster.
ノード加入時、Primary Componentのstate UUIDと、自身のUUIDを比較し、一致しなければstate transferを要求します。
このとき、grastate.datにUUIDとseqnoが記載されてあれば、seqnoの差分だけ追いかけるのですが、そもそもこのファイルがないのでシーケンスの比較ができず、ISTが選択できないため、SSTを行います。
このあたりの動作はログからも確認できます。
171219 8:12:50 [Note] WSREP: Flow-control interval: [28, 28]
171219 8:12:50 [Note] WSREP: Shifting OPEN -> PRIMARY (TO: 3189)
171219 8:12:50 [Note] WSREP: State transfer required:
Group state: cf819ec9-e382-11e7-a390-768e47ae6c01:3189
Local state: 00000000-0000-0000-0000-000000000000:-1
171219 8:12:50 [Note] WSREP: New cluster view: global state: cf819ec9-e382-11e7-a390-768e47ae6c01:3189, view# 16: Primary, number of nodes: 3, my index: 2, protocol version 3
171219 8:12:50 [Warning] WSREP: Gap in state sequence. Need state transfer.
171219 8:12:50 [Note] WSREP: Running: 'wsrep_sst_rsync --role 'joiner' --address '192.168.100.102' --auth '' --datadir '/var/lib/mysql/' --defaults-file '/etc/my.cnf' --parent '8429''
171219 8:12:50 [Note] WSREP: Prepared SST request: rsync|192.168.100.102:4444/rsync_sst
171219 8:12:50 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification.
171219 8:12:50 [Note] WSREP: REPL Protocols: 7 (3, 2)
171219 8:12:50 [Note] WSREP: Service thread queue flushed.
171219 8:12:50 [Note] WSREP: Assign initial position for certification: 3189, protocol version: 3
171219 8:12:50 [Note] WSREP: Service thread queue flushed.
171219 8:12:50 [Warning] WSREP: Failed to prepare for incremental state transfer: Local state UUID (00000000-0000-0000-0000-000000000000) does not match group state UUID (cf819ec9-e382-11e7-a390-768e47ae6c01): 1 (Operation not permitted)
at galera/src/replicator_str.cpp:prepare_for_IST():456. IST will be unavailable.
171219 8:12:50 [Note] WSREP: Member 2.0 (maria2) requested state transfer from '*any*'. Selected 0.0 (maria3)(SYNCED) as donor.
171219 8:12:50 [Note] WSREP: Shifting PRIMARY -> JOINER (TO: 3189)
171219 8:12:50 [Note] WSREP: Requesting state transfer: success, donor: 0
171219 8:12:53 [Note] WSREP: (f74577ba, 'tcp://0.0.0.0:4567') turning message relay requesting off
171219 8:14:08 [Note] WSREP: 0.0 (maria3): State transfer to 2.0 (maria2) complete.
171219 8:14:08 [Note] WSREP: Member 0.0 (maria3) synced with group.
WSREP_SST: [INFO] Joiner cleanup. (20171219 08:14:08.820)
WSREP_SST: [INFO] Joiner cleanup done. (20171219 08:14:09.333)
171219 8:14:09 [Note] WSREP: SST complete, seqno: 3189
加入時に、Group Communicationをとって、group Stateとlocal stateを比較します。grastate.datに保存されている情報がないので、新規加入(provision)と解釈され、local stateは00000000-0000-0000-0000-000000000000になります。
ISTを試そうとするんですが、state UUIDが異なるため、SSTを行います。このときjoinerはmaria2、donorはmaria3が選ばれました。
検証
事前にテスト用DBを作成し、データを格納しておきましょう。
MariaDB [(none)]> create database sst_blocking_test;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> use sst_blocking_test
Database changed
MariaDB [sst_blocking_test]> CREATE TABLE blocking_test (id int, name varchar(20));
Query OK, 0 rows affected (0.01 sec)
MariaDB [sst_blocking_test]> INSERT INTO blocking_test (id, name) VALUES (1, 'hogehoge');
Query OK, 1 row affected (0.00 sec)
MariaDB [sst_blocking_test]> SELECT * FROM blocking_test;
+------+----------+
| id | name |
+------+----------+
| 1 | hogehoge |
+------+----------+
1 row in set (0.00 sec)
donorを確実にするため、2台体制にしておきます。
grastate.datを削除してサービスを起動します。
# rm -f /var/lib/mysql/grastate.dat
# service mysql start
Starting MySQL....SST in progress, setting sleep higher...... SUCCESS!
約1分で加入しました。その間、donorノードで以下を実行。
MariaDB [(none)]> SHOW STATUS LIKE 'wsrep_local_state_comment';
+---------------------------+----------------+
| Variable_name | Value |
+---------------------------+----------------+
| wsrep_local_state_comment | Donor/Desynced |
+---------------------------+----------------+
1 row in set (0.00 sec)
MariaDB [(none)]> INSERT INTO sst_blocking_test.blocking_test (id, name) VALUES (2, 'fugafuga');
Query OK, 1 row affected (41.42 sec)
MariaDB [sst_blocking_test]> SELECT * FROM sst_blocking_test.blocking_test;
+------+----------+
| id | name |
+------+----------+
| 1 | hogehoge |
| 2 | fugafuga |
+------+----------+
2 rows in set (0.01 sec)
40秒ほどINSERTが待たされているので、blockingになってることがわかりました。
おわりに
1台の状態からクラスタ復旧するときは、その加入時間だけサービスが停止してしまうことがわかりました。
mysqldumpやxtrabackupのSST methodは使ったことないんですが、xtrabackupはBrieflyとのことですが、MyISAMテーブルのロックだけかけるようですね。
xtrabackup only blocks the donor for the short period of time it takes to copy the MyISAM tables, (for instance, the system tables).
mysqldumpもinnodbに関しては--single-transaction相当の動きをしてくれればblockingにする必要ないと思うんだけどなー。(MyISAMのロックだけで)
以上、実験でした。