sql >> データベース >  >> RDS >> Mysql

MySQL InnoDB Cluster 8.0-完全な操作のウォークスルー:パート2

    このブログの最初の部分では、MySQL InnoDBクラスターのデプロイのウォークスルーについて説明し、アプリケーションが専用の読み取り/書き込みポートを介してクラスターに接続する方法の例を示しました。

    この操作ウォークスルーでは、進行中のクラスター保守操作の一部としてInnoDBクラスターを監視、管理、およびスケーリングする方法の例を示します。ブログの最初の部分で展開したものと同じクラスターを使用します。次の図は、アーキテクチャを示しています。

    3ノードのMySQLグループレプリケーションと1つのアプリケーションサーバーが実行されていますMySQLルーター。すべてのサーバーはUbuntu18.04Bionicで実行されています。

    MySQLInnoDBクラスターコマンドオプション

    いくつかの例と説明に進む前に、以下に示すように、help()関数を使用して、クラスターコンポーネント用のMySQLクラスターの各関数の説明を取得できることを知っておくとよいでしょう。

    $ mysqlsh
    MySQL|localhost:3306 ssl|JS> shell.connect("[email protected]:3306");
    MySQL|db1:3306 ssl|JS> cluster = dba.getCluster();
    <Cluster:my_innodb_cluster>
    MySQL|db1:3306 ssl|JS> cluster.help()

    次のリストは、MySQL CommunityServer8.0.18のMySQLShell8.0.18で使用可能な機能を示しています。

    • addInstance(instance [、options])-インスタンスをクラスターに追加します。
    • checkInstanceState(instance)-クラスターに関連するインスタンスのgtid状態を確認します。
    • describe()-クラスターの構造を記述します。
    • disconnect()-クラスターオブジェクトによって使用されるすべての内部セッションを切断します。
    • dissolve([options])-レプリケーションを非アクティブ化し、ReplicaSetsをクラスターから登録解除します。
    • forceQuorumUsingPartitionOf(instance [、password])-クォーラムの喪失からクラスターを復元します。
    • getName()-クラスターの名前を取得します。
    • help([member])-このクラスとそのメンバーに関するヘルプを提供します
    • options([options])-クラスター構成オプションを一覧表示します。
    • rejoinInstance(instance [、options])-インスタンスをクラスターに再参加させます。
    • removeInstance(instance [、options])-クラスターからインスタンスを削除します。
    • rescan([options])-クラスターを再スキャンします。
    • resetRecoveryAccountsPassword(options)-クラスターのリカバリアカウントのパスワードをリセットします。
    • setInstanceOption(instance、option、value)-クラスターメンバーの構成オプションの値を変更します。
    • setOption(option、value)-クラスター全体の構成オプションの値を変更します。
    • setPrimaryInstance(instance)-特定のクラスターメンバーを新しいプライマリとして選択します。
    • status([options])-クラスターのステータスを説明します。
    • switchToMultiPrimaryMode()-クラスターをマルチプライマリモードに切り替えます。
    • switchToSinglePrimaryMode([instance])-クラスターをシングルプライマリモードに切り替えます。

    クラスターの監視、管理、スケーリングに役立つほとんどの機能を調べます。

    MySQLInnoDBクラスター操作の監視

    クラスターステータス

    クラスタのステータスを確認するには、最初にMySQLシェルコマンドラインを使用してから、example @ sqldat.com {one-of-the-db-nodes}:

    として接続します。
    $ mysqlsh
    MySQL|localhost:3306 ssl|JS> shell.connect("[email protected]:3306");

    次に、「cluster」というオブジェクトを作成し、AdminAPIを使用してInnoDBクラスター管理関数へのアクセスを提供する「dba」グローバルオブジェクトとして宣言します(MySQL Shell APIドキュメントを確認してください):

    MySQL|db1:3306 ssl|JS> cluster = dba.getCluster();
    <Cluster:my_innodb_cluster>

    次に、オブジェクト名を使用して、「dba」オブジェクトのAPI関数を呼び出すことができます。

    MySQL|db1:3306 ssl|JS> cluster.status()
    {
        "clusterName": "my_innodb_cluster",
        "defaultReplicaSet": {
            "name": "default",
            "primary": "db1:3306",
            "ssl": "REQUIRED",
            "status": "OK",
            "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
            "topology": {
                "db1:3306": {
                    "address": "db1:3306",
                    "mode": "R/W",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                },
                "db2:3306": {
                    "address": "db2:3306",
                    "mode": "R/O",
                    "readReplicas": {},
                    "replicationLag": "00:00:09.061918",
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                },
                "db3:3306": {
                    "address": "db3:3306",
                    "mode": "R/O",
                    "readReplicas": {},
                    "replicationLag": "00:00:09.447804",
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                }
            },
            "topologyMode": "Single-Primary"
        },
        "groupInformationSourceMember": "db1:3306"
    }

    出力はかなり長いですが、マップ構造を使用してフィルターで除外できます。たとえば、db3のレプリケーションラグのみを表示する場合は、次のように実行できます。

    MySQL|db1:3306 ssl|JS> cluster.status().defaultReplicaSet.topology["db3:3306"].replicationLag
    00:00:09.447804

    レプリケーションラグは、レプリカセットのプライマリメンバーの書き込み強度とgroup_replication_flow_control_ *変数に応じて、グループレプリケーションで発生するものであることに注意してください。ここでは、このトピックについて詳しく説明しません。このブログ投稿をチェックして、グループレプリケーションのパフォーマンスとフロー制御についてさらに理解してください。

    もう1つの同様の関数はdescribe()関数ですが、これはもう少し単純です。すべての情報、ReplicaSets、およびインスタンスを含むクラスターの構造について説明します。

    MySQL|db1:3306 ssl|JS> cluster.describe()
    {
        "clusterName": "my_innodb_cluster",
        "defaultReplicaSet": {
            "name": "default",
            "topology": [
                {
                    "address": "db1:3306",
                    "label": "db1:3306",
                    "role": "HA"
                },
                {
                    "address": "db2:3306",
                    "label": "db2:3306",
                    "role": "HA"
                },
                {
                    "address": "db3:3306",
                    "label": "db3:3306",
                    "role": "HA"
                }
            ],
            "topologyMode": "Single-Primary"
        }
    }

    同様に、マップ構造を使用してJSON出力をフィルタリングできます。

    MySQL|db1:3306 ssl|JS> cluster.describe().defaultReplicaSet.topologyMode
    Single-Primary

    プライマリノードがダウンしたとき(この場合はdb1)、出力は次を返しました:

    MySQL|db1:3306 ssl|JS> cluster.status()
    {
        "clusterName": "my_innodb_cluster",
        "defaultReplicaSet": {
            "name": "default",
            "primary": "db2:3306",
            "ssl": "REQUIRED",
            "status": "OK_NO_TOLERANCE",
            "statusText": "Cluster is NOT tolerant to any failures. 1 member is not active",
            "topology": {
                "db1:3306": {
                    "address": "db1:3306",
                    "mode": "n/a",
                    "readReplicas": {},
                    "role": "HA",
                    "shellConnectError": "MySQL Error 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 104",
                    "status": "(MISSING)"
                },
                "db2:3306": {
                    "address": "db2:3306",
                    "mode": "R/W",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                },
                "db3:3306": {
                    "address": "db3:3306",
                    "mode": "R/O",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                }
            },
            "topologyMode": "Single-Primary"
        },
        "groupInformationSourceMember": "db2:3306"
    }

    ステータスOK_NO_TOLERANCEに注意してください。この場合、クラスターはまだ稼働していますが、3つに1つのノードが使用できなくなった後はそれ以上の障害に耐えることができません。主な役割はdb2によって自動的に引き継がれ、アプリケーションからのデータベース接続は、MySQLルーターを介して接続する場合、正しいノードに再ルーティングされます。 db1がオンラインに戻ると、次のステータスが表示されます。

    MySQL|db1:3306 ssl|JS> cluster.status()
    {
        "clusterName": "my_innodb_cluster",
        "defaultReplicaSet": {
            "name": "default",
            "primary": "db2:3306",
            "ssl": "REQUIRED",
            "status": "OK",
            "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
            "topology": {
                "db1:3306": {
                    "address": "db1:3306",
                    "mode": "R/O",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                },
                "db2:3306": {
                    "address": "db2:3306",
                    "mode": "R/W",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                },
                "db3:3306": {
                    "address": "db3:3306",
                    "mode": "R/O",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                }
            },
            "topologyMode": "Single-Primary"
        },
        "groupInformationSourceMember": "db2:3306"
    }

    これは、db1が使用可能になっているが、読み取り専用が有効になっているセカンダリとして機能していることを示しています。ノードに問題が発生するまで、主な役割は引き続きdb2に割り当てられ、そこで次の使用可能なノードに自動的にフェイルオーバーされます。

    インスタンスの状態を確認

    checkInstanceState()関数を使用して、MySQLノードをクラスターに追加する計画を立てる前に、MySQLノードの状態を確認できます。インスタンスが実行されたGTIDをクラスター上で実行/パージされたGTIDとともに分析して、インスタンスがクラスターに対して有効かどうかを判断します。

    以下は、クラスターの一部になる前のスタンドアロンモードでのdb3のインスタンス状態を示しています。

    MySQL|db1:3306 ssl|JS> cluster.checkInstanceState("db3:3306")
    Cluster.checkInstanceState: The instance 'db3:3306' is a standalone instance but is part of a different InnoDB Cluster (metadata exists, instance does not belong to that metadata, and Group Replication is not active).

    ノードがすでにクラスターの一部である場合は、次の情報を取得する必要があります。

    MySQL|db1:3306 ssl|JS> cluster.checkInstanceState("db3:3306")
    Cluster.checkInstanceState: The instance 'db3:3306' already belongs to the ReplicaSet: 'default'.
    「クエリ可能な」状態を監視する

    MySQL Shellを使用すると、組み込みの\showおよび\watchコマンドを使用して、管理クエリをリアルタイムで監視できるようになりました。たとえば、次を使用して接続されたスレッドのリアルタイム値を取得できます。

    MySQL|db1:3306 ssl|JS> \show query SHOW STATUS LIKE '%thread%';

    または、現在のMySQLプロセスリストを取得します:

    MySQL|db1:3306 ssl|JS> \show query SHOW FULL PROCESSLIST

    次に、\watchコマンドを使用して\showコマンドと同じ方法でレポートを実行できますが、Ctrl + Cを使用してコマンドをキャンセルするまで、定期的に結果を更新します。次の例:

    MySQL|db1:3306 ssl|JS> \watch query SHOW STATUS LIKE '%thread%';
    MySQL|db1:3306 ssl|JS> \watch query --interval=1 SHOW FULL PROCESSLIST
    デフォルトの更新間隔は2秒です。 --intervalフラグを使用して値を変更し、0.1から86400までの値を指定できます。

    MySQLInnoDBクラスター管理操作

    プライマリスイッチオーバー

    プライマリインスタンスは、レプリケーショングループのリーダーと見なすことができるノードであり、読み取りおよび書き込み操作を実行する機能があります。シングルプライマリトポロジモードでは、クラスタごとに1つのプライマリインスタンスのみが許可されます。このトポロジはレプリカセットとも呼ばれ、ロックの競合から保護するグループレプリケーションに推奨されるトポロジモードです。

    プライマリインスタンスの切り替えを実行するには、clusteradminユーザーとしてデータベースノードの1つにログインし、setPrimaryInstance()関数を使用してプロモートするデータベースノードを指定します。

    MySQL|db1:3306 ssl|JS> shell.connect("[email protected]:3306");
    MySQL|db1:3306 ssl|JS> cluster.setPrimaryInstance("db1:3306");
    Setting instance 'db1:3306' as the primary instance of cluster 'my_innodb_cluster'...
    
    Instance 'db2:3306' was switched from PRIMARY to SECONDARY.
    Instance 'db3:3306' remains SECONDARY.
    Instance 'db1:3306' was switched from SECONDARY to PRIMARY.
    
    WARNING: The cluster internal session is not the primary member anymore. For cluster management operations please obtain a fresh cluster handle using <Dba>.getCluster().
    
    The instance 'db1:3306' was successfully elected as primary.

    db1を新しいプライマリコンポーネントとしてプロモートし、db2を置き換え、db3はセカンダリノードのままにしました。

    クラスターのシャットダウン

    アプリケーションサーバーで最初にMySQLルーターサービスを停止して(実行中の場合)、クラスターを正常にシャットダウンするための最良の方法:

    $ myrouter/stop.sh

    上記の手順は、アプリケーションによる偶発的な書き込みに対するクラスター保護を提供します。次に、標準のMySQL stopコマンドを使用して一度に1つのデータベースノードをシャットダウンするか、必要に応じてシステムシャットダウンを実行します。

    $ systemctl stop mysql
    シャットダウン後のクラスターの開始

    クラスターが完全に停止した場合、またはクリーンシャットダウン後にクラスターを開始したい場合は、dba.rebootClusterFromCompleteOutage()関数を使用してクラスターが正しく再構成されていることを確認できます。すべてのメンバーがオフラインの場合、クラスターをオンラインに戻すだけです。クラスターが完全に停止した場合は、インスタンスを開始する必要があります。そうしないと、クラスターを開始できません。

    したがって、すべてのMySQLサーバーが起動して実行されていることを確認します。すべてのデータベースノードで、mysqldプロセスが実行されているかどうかを確認します。

    $ ps -ef | grep -i mysql

    次に、プライマリノードとなるデータベースサーバーを1つ選択し、MySQLシェルを介して接続します。

    MySQL|JS> shell.connect("[email protected]:3306");

    そのホストから次のコマンドを実行して、ホストを起動します。

    MySQL|db1:3306 ssl|JS> cluster = dba.rebootClusterFromCompleteOutage()
    次の質問が表示されます。

    上記が完了したら、クラスターのステータスを確認できます。

    MySQL|db1:3306 ssl|JS> cluster.status()

    この時点で、db1はプライマリノードおよびライターです。残りは二次会員になります。 db2またはdb3を1次としてクラスターを開始する場合は、shell.connect()関数を使用して対応するノードに接続し、その特定のノードからrebootClusterFromCompleteOutage()を実行できます。

    その後、MySQLルーターサービスを開始し(開始されていない場合)、アプリケーションをクラスターに再度接続させることができます。

    メンバーとクラスターのオプションの設定

    クラスタ全体のオプションを取得するには、次のコマンドを実行するだけです。

    MySQL|db1:3306 ssl|JS> cluster.options()

    上記は、レプリカセットのグローバルオプションと、クラスター内のメンバーごとの個々のオプションを示しています。この関数は、クラスターのすべてのメンバーのInnoDBクラスター構成オプションを変更します。サポートされているオプションは次のとおりです。

    • clusterName:クラスター名を定義する文字列値。
    • exitStateAction:グループレプリケーションの終了状態アクションを示す文字列値。
    • memberWeight:フェイルオーバー時の自動予備選挙の重みのパーセンテージを含む整数値。
    • failoverConsistency:クラスターが提供する一貫性を保証する文字列値。
    • 一貫性:クラスターが提供する一貫性を保証する文字列値。
    • expelTimeout:クラスターメンバーが応答しないメンバーをクラスターから削除する前に待機する時間を秒単位で定義する整数値。
    • autoRejoinTries:インスタンスが追放された後にクラスターへの再参加を試みる回数を定義する整数値。
    • disableClone:クラスターでのクローンの使用を無効にするために使用されるブール値。

    他の関数と同様に、出力はマップ構造でフィルタリングできます。次のコマンドは、db2のオプションのみをリストします。

    MySQL|db1:3306 ssl|JS> cluster.options().defaultReplicaSet.topology["db2:3306"]

    help()関数を使用して上記のリストを取得することもできます:

    MySQL|db1:3306 ssl|JS> cluster.help("setOption")

    次のコマンドは、すべてのメンバーでmemberWeightというオプションを60(50から)に設定する例を示しています。

    MySQL|db1:3306 ssl|JS> cluster.setOption("memberWeight", 60)
    Setting the value of 'memberWeight' to '60' in all ReplicaSet members ...
    
    Successfully set the value of 'memberWeight' to '60' in the 'default' ReplicaSet.

    setInstanceOption()関数を使用して、MySQL Shellを介して構成管理を自動的に実行し、それに応じてデータベースホスト、オプション名、および値を渡すこともできます。

    MySQL|db1:3306 ssl|JS> cluster = dba.getCluster()
    MySQL|db1:3306 ssl|JS> cluster.setInstanceOption("db1:3306", "memberWeight", 90)

    サポートされているオプションは次のとおりです。

    • exitStateAction:グループレプリケーションの終了状態アクションを示す文字列値。
    • memberWeight:フェイルオーバー時の自動予備選挙の重みのパーセンテージを含む整数値。
    • autoRejoinTries:インスタンスが追放された後にクラスターへの再参加を試みる回数を定義する整数値。
    • インスタンスの文字列識別子にラベルを付けます。
    マルチプライマリ/シングルプライマリモードへの切り替え

    デフォルトでは、InnoDBクラスターはシングルプライマリで構成されており、一度に読み取りと書き込みを実行できるメンバーは1つだけです。これは、クラスターを実行するための最も安全で推奨される方法であり、ほとんどのワークロードに適しています。

    ただし、アプリケーションロジックが分散書き込みを処理できる場合は、クラスター内のすべてのメンバーが読み取りと書き込みを同時に処理できるマルチプライマリモードに切り替えることをお勧めします。シングルプライマリモードからマルチプライマリモードに切り替えるには、switchToMultiPrimaryMode()関数を使用するだけです。

    MySQL|db1:3306 ssl|JS> cluster.switchToMultiPrimaryMode()
    Switching cluster 'my_innodb_cluster' to Multi-Primary mode...
    
    Instance 'db2:3306' was switched from SECONDARY to PRIMARY.
    Instance 'db3:3306' was switched from SECONDARY to PRIMARY.
    Instance 'db1:3306' remains PRIMARY.
    
    The cluster successfully switched to Multi-Primary mode.

    確認方法:

    MySQL|db1:3306 ssl|JS> cluster.status()
    {
        "clusterName": "my_innodb_cluster",
        "defaultReplicaSet": {
            "name": "default",
            "ssl": "REQUIRED",
            "status": "OK",
            "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
            "topology": {
                "db1:3306": {
                    "address": "db1:3306",
                    "mode": "R/W",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                },
                "db2:3306": {
                    "address": "db2:3306",
                    "mode": "R/W",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                },
                "db3:3306": {
                    "address": "db3:3306",
                    "mode": "R/W",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.18"
                }
            },
            "topologyMode": "Multi-Primary"
        },
        "groupInformationSourceMember": "db1:3306"
    }

    マルチプライマリモードでは、すべてのノードがプライマリであり、読み取りと書き込みを処理できます。シングルライターポート(6446)でMySQLルーターを介して新しい接続を送信する場合、この例のように、接続は1つのノードにのみ送信されます。db1:

    (app-server)$ for i in {1..3}; do mysql -usbtest -p -h192.168.10.40 -P6446 -e 'select @@hostname, @@read_only, @@super_read_only'; done
    
    +------------+-------------+-------------------+
    | @@hostname | @@read_only | @@super_read_only |
    +------------+-------------+-------------------+
    | db1        | 0           | 0                 |
    +------------+-------------+-------------------+
    
    +------------+-------------+-------------------+
    | @@hostname | @@read_only | @@super_read_only |
    +------------+-------------+-------------------+
    | db1        | 0           | 0                 |
    +------------+-------------+-------------------+
    
    +------------+-------------+-------------------+
    | @@hostname | @@read_only | @@super_read_only |
    +------------+-------------+-------------------+
    | db1        | 0           | 0                 |
    +------------+-------------+-------------------+

    アプリケーションがマルチライターポート(6447)に接続する場合、接続はラウンドロビンアルゴリズムを介してすべてのメンバーに負荷分散されます:

    (app-server)$ for i in {1..3}; do mysql -usbtest -ppassword -h192.168.10.40 -P6447 -e 'select @@hostname, @@read_only, @@super_read_only'; done
    
    +------------+-------------+-------------------+
    | @@hostname | @@read_only | @@super_read_only |
    +------------+-------------+-------------------+
    | db2        | 0           | 0                 |
    +------------+-------------+-------------------+
    
    +------------+-------------+-------------------+
    | @@hostname | @@read_only | @@super_read_only |
    +------------+-------------+-------------------+
    | db3        | 0           | 0                 |
    +------------+-------------+-------------------+
    
    +------------+-------------+-------------------+
    | @@hostname | @@read_only | @@super_read_only |
    +------------+-------------+-------------------+
    | db1        | 0           | 0                 |
    +------------+-------------+-------------------+

    上記の出力からわかるように、すべてのノードはread_only=OFFで読み取りと書き込みを処理できます。マルチライターポート(6447)に接続することにより、すべてのメンバーに安全な書き込みを配布し、競合する書き込みまたは大量の書き込みをシングルライターポート(6446)に送信できます。

    シングルプライマリモードに戻すには、switchToSinglePrimaryMode()関数を使用して、1つのメンバーをプライマリノードとして指定します。この例では、db1を選択しました:

    MySQL|db1:3306 ssl|JS> cluster.switchToSinglePrimaryMode("db1:3306");
    
    Switching cluster 'my_innodb_cluster' to Single-Primary mode...
    
    Instance 'db2:3306' was switched from PRIMARY to SECONDARY.
    Instance 'db3:3306' was switched from PRIMARY to SECONDARY.
    Instance 'db1:3306' remains PRIMARY.
    
    WARNING: Existing connections that expected a R/W connection must be disconnected, i.e. instances that became SECONDARY.
    
    The cluster successfully switched to Single-Primary mode.

    この時点で、db1は読み取り専用を無効にして構成されたプライマリノードになり、残りは読み取り専用を有効にしてセカンダリとして構成されます。

    MySQLInnoDBクラスタースケーリング操作

    スケールアップ(新しいDBノードの追加)

    新しいインスタンスを追加するときは、レプリケーショングループへの参加を許可する前に、ノードを最初にプロビジョニングする必要があります。プロビジョニングプロセスはMySQLによって自動的に処理されます。また、前に説明したように、checkInstanceState()関数を使用して、ノードがクラスターに参加するのに有効かどうかを最初にインスタンスの状態を確認できます。

    新しいDBノードを追加するには、addInstances()関数を使用して、ホストを指定します。

    MySQL|db1:3306 ssl|JS> cluster.addInstance("db3:3306")

    新しいインスタンスを追加すると、次のようになります。

    次のコマンドで新しいクラスターサイズを確認します:

    MySQL|db1:3306 ssl|JS> cluster.status() //or cluster.describe()

    MySQLルーターは、追加されたノードdb3を負荷分散セットに自動的に含めます。

    スケールダウン(ノードの削除)

    ノードを削除するには、削除するDBノード以外の任意のDBノードに接続し、データベースインスタンス名でremoveInstance()関数を使用します。

    MySQL|db1:3306 ssl|JS> shell.connect("[email protected]:3306");
    MySQL|db1:3306 ssl|JS> cluster = dba.getCluster()
    MySQL|db1:3306 ssl|JS> cluster.removeInstance("db3:3306")

    インスタンスを削除すると、次のようになります。

    次のコマンドで新しいクラスターサイズを確認します:

    MySQL|db1:3306 ssl|JS> cluster.status() //or cluster.describe()

    MySQLルーターは、削除されたノードdb3を負荷分散セットから自動的に除外します。

    新しいレプリケーションスレーブの追加

    任意のクラスターノードからの非同期レプリケーションスレーブレプリケートを使用して、InnoDBクラスターをスケールアウトできます。スレーブはクラスターに緩く結合されており、クラスターのパフォーマンスに影響を与えることなく、重い負荷を処理できます。スレーブは、災害復旧の目的でデータベースのライブコピーにすることもできます。マルチプライマリモードでは、スレーブを専用のMySQL読み取り専用プロセッサとして使用して、読み取りワークロードをスケールアウトしたり、分析操作を実行したり、専用のバックアップサーバーとして使用したりできます。

    スレーブサーバーで、最新のAPT構成パッケージをダウンロードしてインストールし(構成ウィザードでMySQL 8.0を選択)、APTキーをインストールし、リポジトリを更新してMySQLサーバーをインストールします。

    $ wget https://repo.mysql.com/apt/ubuntu/pool/mysql-apt-config/m/mysql-apt-config/mysql-apt-config_0.8.14-1_all.deb
    $ dpkg -i mysql-apt-config_0.8.14-1_all.deb
    $ apt-key adv --recv-keys --keyserver ha.pool.sks-keyservers.net 5072E1F5
    $ apt-get update
    $ apt-get -y install mysql-server mysql-shell

    MySQL構成ファイルを変更して、サーバーをレプリケーションスレーブ用に準備します。テキストエディタで設定ファイルを開きます:

    $ vim /etc/mysql/mysql.conf.d/mysqld.cnf

    そして、次の行を追加します:

    server-id = 1044 # must be unique across all nodes
    gtid-mode = ON
    enforce-gtid-consistency = ON
    log-slave-updates = OFF
    read-only = ON
    super-read-only = ON
    expire-logs-days = 7

    スレーブでMySQLサーバーを再起動して、変更を適用します。

    $ systemctl restart mysql

    InnoDBクラスターサーバーの1つ(db3を選択)で、レプリケーションスレーブユーザーを作成し、その後に完全なMySQLダンプを作成します。

    $ mysql -uroot -p
    mysql> CREATE USER 'repl_user'@'192.168.0.44' IDENTIFIED BY 'password';
    mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.0.44';
    mysql> exit
    $ mysqldump -uroot -p --single-transaction --master-data=1 --all-databases --triggers --routines --events > dump.sql
    ダンプファイルをdb3からスレーブに転送します:

    $ scp dump.sql [email protected]:~

    そして、スレーブで復元を実行します:

    $ mysql -uroot -p < dump.sql

    master-data =1の場合、MySQLダンプファイルは、実行およびパージされたGTID値を自動的に構成します。復元後、スレーブサーバーで次のステートメントを使用して確認できます。

    $ mysql -uroot -p
    mysql> show global variables like '%gtid_%';
    +----------------------------------+----------------------------------------------+
    | Variable_name                    | Value                                        |
    +----------------------------------+----------------------------------------------+
    | binlog_gtid_simple_recovery      | ON                                           |
    | enforce_gtid_consistency         | ON                                           |
    | gtid_executed                    | d4790339-0694-11ea-8fd5-02f67042125d:1-45886 |
    | gtid_executed_compression_period | 1000                                         |
    | gtid_mode                        | ON                                           |
    | gtid_owned                       |                                              |
    | gtid_purged                      | d4790339-0694-11ea-8fd5-02f67042125d:1-45886 |
    +----------------------------------+----------------------------------------------+

    いいね。次に、レプリケーションリンクを構成し、スレーブでレプリケーションスレッドを開始できます。

    mysql> CHANGE MASTER TO MASTER_HOST = '192.168.10.43', MASTER_USER = 'repl_user', MASTER_PASSWORD = 'password', MASTER_AUTO_POSITION = 1;
    mysql> START SLAVE;

    レプリケーションの状態を確認し、次のステータスが「はい」を返すことを確認します。

    mysql> show slave status\G
    ...
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
    ...

    この時点で、アーキテクチャは次のようになっています。

    MySQLInnoDBクラスターに関する一般的な問題

    メモリの枯渇

    MySQL8.0でMySQLShellを使用する場合、インスタンスが1GBのRAMで構成されていると、常に次のエラーが発生していました。

    Can't create a new thread (errno 11); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug (MySQL Error 1135)

    各ホストのRAMを2GBのRAMにアップグレードすると、問題が解決しました。どうやら、MySQL8.0コンポーネントは効率的に動作するためにより多くのRAMを必要とします。

    Lost Connection to MySQL Server

    In case the primary node goes down, you would probably see the "lost connection to MySQL server error" when trying to query something on the current session:

    MySQL|db1:3306 ssl|JS> cluster.status()
    Cluster.status: Lost connection to MySQL server during query (MySQL Error 2013)
    
    MySQL|db1:3306 ssl|JS> cluster.status()
    Cluster.status: MySQL server has gone away (MySQL Error 2006)

    The solution is to re-declare the object once more:

    MySQL|db1:3306 ssl|JS> cluster = dba.getCluster()
    <Cluster:my_innodb_cluster>
    MySQL|db1:3306 ssl|JS> cluster.status()

    At this point, it will connect to the newly promoted primary node to retrieve the cluster status.

    Node Eviction and Expelled

    In an event where communication between nodes is interrupted, the problematic node will be evicted from the cluster without any delay, which is not good if you are running on a non-stable network. This is what it looks like on db2 (the problematic node):

    2019-11-14T07:07:59.344888Z 0 [ERROR] [MY-011505] [Repl] Plugin group_replication reported: 'Member was expelled from the group due to network failures, changing member status to ERROR.'
    2019-11-14T07:07:59.371966Z 0 [ERROR] [MY-011712] [Repl] Plugin group_replication reported: 'The server was automatically set into read only mode after an error was detected.'

    Meanwhile from db1, it saw db2 was offline:

    2019-11-14T07:07:44.086021Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication reported: 'Member with address db2:3306 has become unreachable.'
    2019-11-14T07:07:46.087216Z 0 [Warning] [MY-011499] [Repl] Plugin group_replication reported: 'Members removed from the group: db2:3306'
    

    To tolerate a bit of delay on node eviction, we can set a higher timeout value before a node is being expelled from the group. The default value is 0, which means expel immediately. Use the setOption() function to set the expelTimeout value:

    Thanks to Frédéric Descamps from Oracle who pointed this out:

    Instead of relying on expelTimeout, it's recommended to set the autoRejoinTries option instead. The value represents the number of times an instance will attempt to rejoin the cluster after being expelled. A good number to start is 3, which means, the expelled member will try to rejoin the cluster for 3 times, which after an unsuccessful auto-rejoin attempt, the member waits 5 minutes before the next try.

    To set this value cluster-wide, we can use the setOption() function:

    MySQL|db1:3306 ssl|JS> cluster.setOption("autoRejoinTries", 3)
    WARNING: Each cluster member will only proceed according to its exitStateAction if auto-rejoin fails (i.e. all retry attempts are exhausted).
    
    Setting the value of 'autoRejoinTries' to '3' in all ReplicaSet members ...
    
    Successfully set the value of 'autoRejoinTries' to '3' in the 'default' ReplicaSet.

    結論

    For MySQL InnoDB Cluster, most of the management and monitoring operations can be performed directly via MySQL Shell (only available from MySQL 5.7.21 and later).


    1. 読み取り/書き込みモードでデータベースを開くことができません

    2. Docker内で実行中のmysqlにmysqlワークベンチを接続する方法は?

    3. MySQLのパフォーマンス:MyISAMとInnoDB

    4. データベースの結果を配列に変換する