MySQL8.0.23の非同期レプリケーション関連の新機能をDocker環境で検証した

# はじめに
グループレプリケーション構成内のプライマリを非同期レプリケーションのレプリカがソースとしてみていたときに
プライマリが変更された時に非同期レプリケーションのレプリカが同期元のソースを自動で切り替えるそうです

https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-23.html

>MySQL Server’s asynchronous connection failover mechanism now supports Group Replication topologies, by automatically monitoring changes to group membership and >distinguishing between primary and secondary servers. 
>When you add a group member to the source list and define it as part of a managed group,
>the asynchronous connection failover mechanism updates the source list to keep it in line with membership changes, adding and removing group members automatically as they >join or leave. The new asynchronous_connection_failover_add_managed() and asynchronous_connection_failover_delete_managed() UDFs are used to add and remove managed sources.

従来の設定ではグループレプリケーションのPrimaryと同期中の非同期レプリケーションの環境は
障害などでPrimaryが変更されると手動で変更後の環境に同期先を向けなおしてやる必要がありました
8.0.23で自動で追随される設定が追加されたようです

この機能は例えばこんなときに使えそうですね
1.データベースのバックアップ環境をグループレプリケーション構成に含めたくないとき
2.グループレプリケーションの台数制約を超過してのレプリカ構成を組んだり（データ不整合はある程度許容可能なことが前提)
3.バッチ処理などグループレプリケーションとの相性が悪い環境を、グループレプリケーションに非同期レプリケーションのスレーブをぶらさげて運用したいとき

今回の試験結果をもとにプロダクション環境の運用はしていません
ですので、運用するときはマニュアルに必ず目を通してください

試験に用いた環境は表題と直接関係がないため、ページの下部に後日記載する予定です


# 環境
Ubuntu 20.04 (Windows10 Pro上のWSL2)
PC:Lenovo E495
CPU:8core
RAM:32GB
Disk:512GB(NVME)

server
【Group Replication構成】
node1:192.168.2.1
node2:192.168.2.2
node3:192.168.2.3
【非同期レプリケーション構成】
node4:192.168.2.4



# グループレプリケーション構成と非同期レプリケーションを組み合わせる


検証の前提条件としてグループレプリケーションの設定は完了しているものとします
参考情報としてページの最下部にAdmin API経由でのグループレプリケーションの組み方を後日記載します


node1(Primary)

グループレプリケーションのPrimary環境でreplユーザを作成します

```sql

use mysql
CREATE USER 'repl'@'%' IDENTIFIED BY 'パスワード文字列';
GRANT SELECT ON performance_schema.* TO 'repl'@'%';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
```

node4


mysql -uroot -p でログインをしてからグループレプリケーションのトポロジーをソースとして設定するためのUDFを実行します

```SQL

mysql> select asynchronous_connection_failover_add_managed('ch1','GroupReplication','012140a4-760c-11eb-9a3b-0242c0a80201','192.168.2.1',3306,'',80,60);
+-------------------------------------------------------------------------------------------------------------------------------------------+
| asynchronous_connection_failover_add_managed('ch1','GroupReplication','012140a4-760c-11eb-9a3b-0242c0a80201','192.168.2.1',3306,'',80,60) |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| The UDF asynchronous_connection_failover_add_managed() executed successfully.                                                             |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.05 sec)
```


設定内容はperformance_schemaで確認します

```SQL
mysql> select * from performance_schema.replication_asynchronous_connection_failover_managed;
+--------------+--------------------------------------+------------------+------------------------------------------------+
| CHANNEL_NAME | MANAGED_NAME                         | MANAGED_TYPE     | CONFIGURATION                                  |
+--------------+--------------------------------------+------------------+------------------------------------------------+
| ch1          | 012140a4-760c-11eb-9a3b-0242c0a80201 | GroupReplication | {"Primary_weight": 80, "Secondary_weight": 60} |
+--------------+--------------------------------------+------------------+------------------------------------------------+
1 row in set (0.00 sec)
```


レプリケーションを開始します
https://dev.mysql.com/doc/refman/8.0/en/replication-asynchronous-connection-failover.html
非同期レプリケーションのフェイルオーバーのためにSOURCE_CONNECTION_AUTO_FAILOVERが新たに増えていました

```SQL
CHANGE REPLICATION SOURCE TO SOURCE_USER='repl', SOURCE_PASSWORD='パスワード文字列', SOURCE_HOST='node1',SOURCE_PORT=3306,SOURCE_RETRY_COUNT=2,SOURCE_CONNECTION_AUTO_FAILOVER=1,SOURCE_AUTO_POSITION=1 FOR CHANNEL 'ch1';
start slave;
```

defaultが1日*60回=60日間、元のソースを見続けるので最小数値にしておきましょう
MASTER_CONNECT_RETRY=60
MASTER_RETRY_COUNT=86400

ERROR
                Last_IO_Error: error connecting to master 'repl@192.168.2.1:3306' - retry-time: 60 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.

初回は同期に失敗します
対処方法はいくつかありますが、今回はキャッシュを生成するために一度mysqlクライアントでログインしました

```sql
mysql -urepl -p -h 192.168.2.1
mysql -urepl -p -h 192.168.2.2
mysql -urepl -p -h 192.168.2.3
```


performance_schemaで状態を確認できます
グループレプリケーションに含まれる3つのnodeがすべて追加されていますね

```SQL
mysql> select * from performance_schema.replication_asynchronous_connection_failover;
+--------------+--------------+------+-------------------+--------+--------------------------------------+
| CHANNEL_NAME | HOST         | PORT | NETWORK_NAMESPACE | WEIGHT | MANAGED_NAME                         |
+--------------+--------------+------+-------------------+--------+--------------------------------------+
| ch1          | 5c911210ba2c | 3306 |                   |     80 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
| ch1          | 83b8bfa38c09 | 3306 |                   |     60 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
| ch1          | e165ee330b48 | 3306 |                   |     60 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
+--------------+--------------+------+-------------------+--------+--------------------------------------+
3 rows in set (0.00 sec)
```

グループレプリケーションのPrimaryがダウンしたときに、非同期レプリケーションのレプリカが接続先の変更を追随するでしょうか
まず、Primaryのnode1を落とします


```shell
#docker-compose stop node1
Stopping work_node1_1 ... done
```

接続が試行されて

```sql


mysql> show replica status\G
*************************** 1. row ***************************
               Slave_IO_State: Reconnecting after a failed master event read
                  Master_Host: 5c911210ba2c
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: 5c911210ba2c-bin.000003
          Read_Master_Log_Pos: 35894
               Relay_Log_File: dbd835e14eaa-relay-bin-ch1.000004
                Relay_Log_Pos: 36115
        Relay_Master_Log_File: 5c911210ba2c-bin.000003
             Slave_IO_Running: Connecting
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 35894
              Relay_Log_Space: 8215473
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 2003
                Last_IO_Error: error reconnecting to master 'repl@5c911210ba2c:3306' - retry-time: 60 retries: 1 message: Can't connect to MySQL server on '5c911210ba2c' (111)
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: 7e21f24c-760b-11eb-b9f1-0242c0a80201
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 2
                  Master_Bind:
      Last_IO_Error_Timestamp: 210223 19:43:09
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 012140a4-760c-11eb-9a3b-0242c0a80201:1-53,
7e21f24c-760b-11eb-b9f1-0242c0a80201:1-5
            Executed_Gtid_Set: 012140a4-760c-11eb-9a3b-0242c0a80201:1-53,
7e21f24c-760b-11eb-b9f1-0242c0a80201:1-5,
7e4a7c94-760b-11eb-ab21-0242c0a80204:1-5
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name: ch1
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)


```

次のnode2が同期先に変化しました


```sql


mysql> show replica status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 83b8bfa38c09
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: 83b8bfa38c09-bin.000002
          Read_Master_Log_Pos: 4028
               Relay_Log_File: dbd835e14eaa-relay-bin-ch1.000005
                Relay_Log_Pos: 503
        Relay_Master_Log_File: 83b8bfa38c09-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 4028
              Relay_Log_Space: 36678
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 3
                  Master_UUID: 7e315bbb-760b-11eb-b1b1-0242c0a80203
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 2
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 012140a4-760c-11eb-9a3b-0242c0a80201:1-53,
7e21f24c-760b-11eb-b9f1-0242c0a80201:1-5
            Executed_Gtid_Set: 012140a4-760c-11eb-9a3b-0242c0a80201:1-53,
7e21f24c-760b-11eb-b9f1-0242c0a80201:1-5,
7e4a7c94-760b-11eb-ab21-0242c0a80204:1-5
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name: ch1
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.01 sec)


```

数秒程度で重み設定を基準に新規Primaryと同期の接続を張り直しました
期待していた動作です


グループレプリケーションのメンバー情報も更新されています

```SQL

mysql> select * from performance_schema.replication_asynchronous_connection_failover;
+--------------+--------------+------+-------------------+--------+--------------------------------------+
| CHANNEL_NAME | HOST         | PORT | NETWORK_NAMESPACE | WEIGHT | MANAGED_NAME                         |
+--------------+--------------+------+-------------------+--------+--------------------------------------+
| ch1          | 83b8bfa38c09 | 3306 |                   |     80 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
| ch1          | e165ee330b48 | 3306 |                   |     60 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
+--------------+--------------+------+-------------------+--------+--------------------------------------+
2 rows in set (0.00 sec)
```

先ほど停止したnode1を起動すると、メンバー情報も更新されました、フェイルバックも発生していません

```shell

docker-compose start node
```


```sql

mysql> select * from performance_schema.replication_asynchronous_connection_failover;
+--------------+--------------+------+-------------------+--------+--------------------------------------+
| CHANNEL_NAME | HOST         | PORT | NETWORK_NAMESPACE | WEIGHT | MANAGED_NAME                         |
+--------------+--------------+------+-------------------+--------+--------------------------------------+
| ch1          | 5c911210ba2c | 3306 |                   |     60 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
| ch1          | 83b8bfa38c09 | 3306 |                   |     80 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
| ch1          | e165ee330b48 | 3306 |                   |     60 | 012140a4-760c-11eb-9a3b-0242c0a80201 |
+--------------+--------------+------+-------------------+--------+--------------------------------------+
3 rows in set (0.00 sec)

```

# まとめ

新規追加された機能でグループレプリケーションと非同期レプリケーションの組み合わせ時でも
可用性を期待できますね


# 参考URL
https://mysqlhighavailability.com/automatic-asynchronous-replication-connection-failover/
https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-innodb-cluster.html
https://dev.mysql.com/doc/refman/8.0/en/replication-functions-source-list.html
https://dev.mysql.com/doc/refman/8.0/en/replication-asynchronous-connection-failover.htm