2020年3月16日月曜日

シングルプライマリーモードだろうとInnoDB Cluster内のデータをズラす方法

TL;DR

  • 単にプライマリーノードで SET sql_log_bin = 0 で効くんだからびっくりだ

動作確認用にd1.t1テーブルを作って2行くらい入れておく。
### node1
mysql> CREATE DATABASE d1;
Query OK, 1 row affected (0.01 sec)

mysql> CREATE TABLE d1.t1 (num SERIAL, val VARCHAR(32));
Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO d1.t1 VALUES (1, 'one');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO d1.t1 VALUES (2, 'two');
Query OK, 1 row affected (0.00 sec)
プライマリーノードで sysbench を使って100万行くらいのテーブルを作る。
### node1
$ sysbench --mysql-user=root oltp_common --table_size=1000000 prepare
sysbench 1.0.17 (using system LuaJIT 2.0.4)

Creating table 'sbtest1'...
Inserting 1000000 records into 'sbtest1'
Creating a secondary index on 'sbtest1'...

### node1
mysql> SELECT COUNT(*) FROM sbtest.sbtest1;                                                 
+----------+
| COUNT(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.32 sec)

### node2
mysql> SELECT COUNT(*) FROM sbtest.sbtest1;
+----------+
| COUNT(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.14 sec)

### node3
mysql> SELECT COUNT(*) FROM sbtest.sbtest1;
+----------+
| COUNT(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.13 sec)
sql_log_bin=OFF でいけるかなと思ったらいけてしまった。
### node1
mysql> SET SESSION sql_log_bin = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM sbtest.sbtest1;
Query OK, 1000000 rows affected (9.65 sec)

### node1
mysql> SELECT COUNT(*) FROM sbtest.sbtest1;
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

### node2
mysql> SELECT COUNT(*) FROM sbtest.sbtest1;
+----------+
| COUNT(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.24 sec)

### node3
mysql> SELECT COUNT(*) FROM sbtest.sbtest1;
+----------+
| COUNT(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.15 sec)
これで何が嬉しいかっていうと、この状態でnode1に対してテキトーな OPTIMIZE TABLE でも投げ続ければ、node2とnode3は十分遅れてくれるだろうっていうこと。
### node1
mysql> OPTIMIZE TABLE sbtest.sbtest1; -- これを5回くらい

mysql> SELECT MEMBER_ID, COUNT_TRANSACTIONS_IN_QUEUE AS queue, COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE FROM performance_schema.replication_group_member_stats;                                        +--------------------------------------+-------+--------------------------------------------+
| MEMBER_ID                            | queue | COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE |
+--------------------------------------+-------+--------------------------------------------+
| ec62dfb5-66e4-11ea-a8d3-12c40920c9ad |     0 |                                          0 |
| ee6bca41-66e4-11ea-b904-123209691891 |     0 |                                          5 |
| f35fec8f-66e4-11ea-9a69-12dd5d4a2e3d |     0 |                                          5 |
+--------------------------------------+-------+--------------------------------------------+
3 rows in set (0.00 sec)
溜まってるのが確認できる。
溜まってる間に追い越してApplyされないのは前々回くらいに試した通りなんだけど。
### node1
mysql> INSERT INTO d1.t1 VALUES (3, 'three');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM t1;
+-----+-------+
| num | val   |
+-----+-------+
|   1 | one   |
|   2 | two   |
|   3 | three |
+-----+-------+
3 rows in set (0.00 sec)

$ for f in /var/lib/mysql/*.0000* ; do mysqlbinlog -vv $f | stdbuf -oL awk '{print "'$f'", $0}'; done | grep INSERT | grep d1
/var/lib/mysql/binlog.000003 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/binlog.000003 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/binlog.000003 ### INSERT INTO `d1`.`t1`

### node2
mysql> SELECT * FROM t1;
+-----+------+
| num | val  |
+-----+------+
|   1 | one  |
|   2 | two  |
+-----+------+
2 rows in set (0.00 sec)

$ for f in /var/lib/mysql/*.0000* ; do mysqlbinlog -vv $f | stdbuf -oL awk '{print "'$f'", $0}'; done | grep INSERT | grep d1                              [22/19445]
/var/lib/mysql/binlog.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/binlog.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/ip-172-31-1-120-relay-bin-group_replication_applier.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/ip-172-31-1-120-relay-bin-group_replication_applier.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/ip-172-31-1-120-relay-bin-group_replication_applier.000002 ### INSERT INTO `d1`.`t1`

### node3
mysql> SELECT * FROM t1;
+-----+------+
| num | val  |
+-----+------+
|   1 | one  |
|   2 | two  |
+-----+------+
2 rows in set (0.00 sec)

$ for f in /var/lib/mysql/*.0000* ; do mysqlbinlog -vv $f | stdbuf -oL awk '{print "'$f'", $0}'; done | grep INSERT | grep d1                               [22/18451]
/var/lib/mysql/binlog.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/binlog.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/ip-172-31-1-48-relay-bin-group_replication_applier.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/ip-172-31-1-48-relay-bin-group_replication_applier.000002 ### INSERT INTO `d1`.`t1`
/var/lib/mysql/ip-172-31-1-48-relay-bin-group_replication_applier.000002 ### INSERT INTO `d1`.`t1`
Applierの方のリレーログはまではちゃんと受け取っている。
DMLだと、DML適用の番になった時にフツーのレプリケーションと同じようにDUP_KEYなりROW_NOT_FOUNDでエラーになって面白くないだけだと思うので、この状態で「グループレプリケーションが遅延しまくっている」のを再現させるのが使いどころじゃないかなあとは思う。
遅延させて何を試していたかはタイトルにそぐわなくなってきたのでまた今度。

続きはこっち → 日々の覚書: わざと件数をズラしたグループレプリケーションで、「遅延中」の動きを観察する

0 件のコメント :

コメントを投稿