TL;DR
SET GLOBAL gtid_purged = '+?'
のプラス付きの記法は、既存のgtid_executed
と1つたりともカブってはいけない。RESET MASTER
ができず、既存のgtid_executed
に足したい場合は差分を取って+
記号で足してやらないといけない
gtid_executed
が空でない時に+
記号なしのSET GLOBAL gtid_purged = ?
した時のエラーが5.7と8.0で変わってた
SET GLOBAL gtid_purged = ?
した時に出ることがある ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed
, よく見たら実は3種類くらいあるっぽかった。
perror
で調べてみると、確かに ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: %s
なので cannot be changed:
までが固定のメッセージで、その理由が後ろに添えられるっぽい。
$ perror 3546
MySQL error code MY-003546 (ER_CANT_SET_GTID_PURGED_DUE_SETS_CONSTRAINTS): @@GLOBAL.GTID_PURGED cannot be changed: %s
my_error
(MySQLがエラーパケットを返す時に使われる関数) で ER_CANT_SET_GTID_PURGED_DUE_SETS_CONSTRAINTS
を渡しているのはMySQL 8.0.32のコードで3か所。
https://github.com/mysql/mysql-server/blob/mysql-8.0.32/sql/rpl_gtid_state.cc#L622-L646
+
記号がついてない時は簡単, if文で1つ目と3つ目に当たる。
mysql80 7> SELECT @@gtid_executed;
+----------------------------------------------+
| @@gtid_executed |
+----------------------------------------------+
| dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1-53562 |
+----------------------------------------------+
1 row in set (0.01 sec)
mysql80 7> SET GLOBAL gtid_purged = 'dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1';
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the new value must be a superset of the old value
mysql80 7> SET GLOBAL gtid_purged = 'dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1-53562';
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED
mysql80 8> SET GLOBAL gtid_purged = 'dddc3a2c-96fe-11ed-ae6d-0201965f8d32:53563';
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the new value must be a superset of the old value
mysql80 8> SET GLOBAL gtid_purged = 'dddc3a2c-96fe-11ed-ae6d-0201965f8d31:1'; -- server_uuid部分が違ってもダメ
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the new value must be a superset of the old value
これは5.7とそれ以前の ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.
に対応していて、「既存の gtid_executed
よりも小さく、かつ大きくなければならない」と言っているのでどう考えても無理。 RESET MASTER
して新たに設定するしかないはず。
ちなみに5.7とそれ以前の MySQL error code MY-001840 (ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.
は8.0ではどこからも呼び出されていない。
+
を付けた時でもエラることはある。エラーメッセージを素直に読むと、既存の部分とカブってはいけないらしい。
mysql80 8> SELECT @@gtid_executed;
+----------------------------------------------+
| @@gtid_executed |
+----------------------------------------------+
| dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1-53562 |
+----------------------------------------------+
1 row in set (0.00 sec)
mysql80 8> SET GLOBAL gtid_purged = '+dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1-53563';
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED
既存の部分とカブらせないようにした↓は通る。
mysql80 8> SET GLOBAL gtid_purged = '+dddc3a2c-96fe-11ed-ae6d-0201965f8d32:53563';
Query OK, 0 rows affected (0.06 sec)
mysql80 8> SELECT @@gtid_executed;
+----------------------------------------------+
| @@gtid_executed |
+----------------------------------------------+
| dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1-53563 |
+----------------------------------------------+
1 row in set (0.00 sec)
mysql80 8> SET GLOBAL gtid_purged = '+dddc3a2c-96fe-11ed-ae6d-0201965f8d31:1'; -- server_uuid部分を変えたものは別gtidなのでもちろん通る
Query OK, 0 rows affected (0.01 sec)
mysql80 8> SELECT @@gtid_executed;
+--------------------------------------------------------------------------------------+
| @@gtid_executed |
+--------------------------------------------------------------------------------------+
| dddc3a2c-96fe-11ed-ae6d-0201965f8d31:1,
dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1-53563 |
+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
これに当たるのはたぶん、
- 「レプリカがしばらく止まっててI/Oスレッドが
'Cannot replicate because the master purged required binary logs. Replicate the missing transactions from elsewhere, or provision a new slave from backup. Consider increasing the master's binary log expiration period. The GTID set sent by the slave is '', and the missing transactions are 'xxx:yyy
で再開できなくなったから、インスタンスはそのままにmysqldumpで上書きして再開させてやろう」と思った時
か - マルチソースレプリケーションを組んでて↑になった時
のパターンだと思う。
前者はインスタンスをつぶしてきれいに再構築するか、 RESET MASTER
してから通せば良いけれど、後者の時は差分を取って綺麗に +
で当ててやらないといけないので、mysqldumpに書いてある SET GLOBAL gtid_purged=?
の部分から
SET GLOBAL gtid_purged= CONCAT('+', GTID_SUBTRACT(/* GTID_SUBTRACTの1つ目の引数がmysqldumpから確認したgtid_purgedにセットしたい値 */ 'dddc3a2c-96fe-11ed-ae6d-0201965f8d31:1,dddc3a2c-96fe-11ed-ae6d-0201965f8d32:1-53563', /* 第2引数をMySQLが認識しているgtid_executedにすると差分がとれる */ @@gtid_executed));
と、差分だけ追加する形でgtid_purgedをセットできた。
しかし、 +
記号がついてない時のエラーは MySQL error code MY-001840 (ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.
で良かったんじゃないかなと思う。
0 件のコメント :
コメントを投稿