Нажмите "Enter" для перехода к содержанию

Потеря кворума MySQL InnoDB Cluster 8.0. Cluster has no quorum and cannot process write transactions: Group has no quorum. Variable ‘group_replication_force_members’ can’t be set to the value of ‘db8-lt.com:33061’ (MYSQLSH 1231)

Если большинство участников вашего набора реплик становятся UNREACHABLE, то в этом наборе нет большинства и он больше не будет иметь кворум и не сможет принимать решения о любых изменениях в наборе реплик. Также если участник группы, ставший UNREACHABLE,вернется в ONLINE, он не сможет снова присоединиться к группе до тех пор, пока она заблокирована.

Разберем ситуацию, когда вы потеряли 2 реплики на трехнодном MySQL InnoDB Cluster 8.0.

1. Потеря двух R/O реплик. Будет потерян кворум. Если вам повезет, то PRIMARY будет продолжать работать в режимеR/W. Если не повезет, то PRIMARYперейдет в режим R/O.

2. Потеря 2 инстансов, один из котрых или оба (Multi-Primary Mode) были R/W. Будет потерян кворум и оставшийся инстанс будет в режиме R/O.

Ниже приведен пример кластера, в котором выключили 2 R/O реплики. PRIMARYперешел из режима R/W в R/O.

MySQL  localhost:33060+ ssl  JS > cluster=dba.getCluster()
WARNING: Cluster has no quorum and cannot process write transactions: Group has no quorum
<Cluster:UAT>
 MySQL  localhost:33060+ ssl  JS > c.status()
{
    "clusterName": "UAT_LOAN",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db8-lt.com:3306",
        "ssl": "REQUIRED",
        "status": "NO_QUORUM",
        "statusText": "Cluster has no quorum as visible from 'db8-lt.com:3306' and cannot process write transactions. 2 members are not active.",
        "topology": {
            "db6-lt.com:3306": {
                "address": "db6-lt.com:3306",
                "memberRole": "SECONDARY",
                "memberState": "(MISSING)",
                "mode": "n/a",
                "readReplicas": {},
                "role": "HA",
                "shellConnectError": "MySQL Error 2003 (HY000): Can't connect to MySQL server on 'db6-lt.com:3306' (111)",
                "status": "UNREACHABLE",
                "version": "8.0.26"
            },
            "db7-lt.com:3306": {
                "address": "db7-lt.com:3306",
                "memberRole": "SECONDARY",
                "memberState": "(MISSING)",
                "mode": "n/a",
                "readReplicas": {},
                "role": "HA",
                "shellConnectError": "MySQL Error 2003 (HY000): Can't connect to MySQL server on 'db7-lt.com:3306' (111)",
                "status": "UNREACHABLE",
                "version": "8.0.26"
            },
            "db8-lt.com:3306": {
                "address": "db8-lt.com:3306",
                "memberRole": "PRIMARY",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.26"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "db8-lt.com:3306"
}

ПРЕДУПРЕЖДЕНИЕ ! ! !

Важно понимать, что в примере выше db8-lt.com был PRIMARY (остается им, но только в режиме R/O) и последняя транзакция зафиксирована в нем. Поэтому мы можем вернуть ему возможность полноценной работы не боясь потери транзакциий. Если у вас PRIMARY стал недоступен и осталась ONLINEтолько R/O реплика, то хорошо подуймате, прежде чем ее активировать. Оцените все риски для бизнеса, т.к. вы очевидно потеряте какое-то количество транзакции.

Чтобы восстановииться после такого сценария, мы должны сначала разблокировать группу (репликации), перенастроив ее так, чтобы учитывались только текущие ONLINEучастники и игнорировались все остальные. Для этого используйте командуcluster.forceQuorumUsingPartitionOf(), передав URI одного из ONLINEчленов вашего набора реплик. Все участники, видимые ONLINE со стороны этого участника, будут добавлены в переопределенную группу.

ПРЕДУПРЕЖДЕНИЕ ! ! !

Обратите внимание, что это опасная команда. Вы можете случайно создать split-brain, что приведет к несогласованности базы данных. Напимер, если члены группы находятся в разных сетях и связь между ними нарушена. В этом случае все члены группы могут быть ONLINE, но члены одной группы будут восприниматься другой как UNREACHABLE, и наоборот. Из-за требования большинства, только одна группа сможет получать обновления, сохраняя согласованность базы данных. При использовании cluster.forceQuorumUsingPartitionOf(), вы можете создать две отдельные группы, которые будут получать обновления по отдельности, что приведет к тому, что ваша база данных будет обрабатывать транзакции независимо друг от друга и окажется в несогласованном состоянии.

Группа из 5 участников, все ONLINE

Группа из 5 участников, разделенная на две

Перед использованием команды cluster.forceQuorumUsingPartitionOf()убедитесь, что все члены группы, которые являются UNREACHABLE, действительно OFFLINE.

Итак, выполняя командуcluster.forceQuorumUsingPartitionOf() мы должны перевести PRIMARYв режим R/W. В большинстве случаев это сработает как надо. После того, как PRIMARY стал R/W, вы восстанавлиаете реплики. Кластер обнаружит реплики, начнет на них накатывать изменения, но вам нужно еще сделать cluster.rescan(), вы увидите данное напоминаие, запросив статус кластера:

MySQL  localhost:33060+ ssl  JS > cluster.status()
{
    "clusterName": "UAT",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db8-lt.com:3306",
        "ssl": "REQUIRED",
        "status": "OK_NO_TOLERANCE",
        "statusText": "Cluster is NOT tolerant to any failures.",
        "topology": {
            "db6-lt.com:3306": {
                "address": "db6-lt.com:3306",
                "instanceErrors": [
                    "NOTE: instance server_id is not registered in the metadata. Use cluster.rescan() to update the metadata."
                ],
                "memberRole": "SECONDARY",
                "mode": "R/O",
                "readReplicas": {},
                "recovery": {
                    "state": "ON"
                },
                "recoveryStatusText": "Distributed recovery in progress",
                "role": "HA",
                "status": "RECOVERING",
                "version": "8.0.26"
            },
            "db8-lt.com:3306": {
                "address": "db8-lt.com:3306",
                "memberRole": "PRIMARY",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.26"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "db8-lt.com:3306"
}

Я же получил ошибку «Variable ‘group_replication_force_members’ can’t be set to the value of ‘db8-lt.com:33061’ (MYSQLSH 1231)»

MySQL  localhost:33060+ ssl  JS > cluster.forceQuorumUsingPartitionOf("gpadmin@db8-lt.com:3306")
Restoring cluster 'UAT' from loss of quorum, by using the partition dbposed of [db8-lt.com:3306]

Restoring the InnoDB cluster ...

Cluster.forceQuorumUsingPartitionOf: Variable 'group_replication_force_members' can't be set to the value of 'db8-lt.com:33061' (MYSQLSH 1231)

Чтобы решить проблему, нужно:

1.Перезапустить инстант mysql:

В режиме sql: restart; В консоли операционной системы: sudo service mysqld restart

2. Подключиться к инстансу и выполнить команду dba.rebootClusterFromdbpleteOutage()

 MySQL  localhost:33060+ ssl  JS > dba.rebootClusterFromdbpleteOutage()
Restoring the default cluster from dbplete outage...

Could not open a connection to 'db6-lt.com:3306': 'MySQL Error 2003: Could not open connection to 'db6-lt.com:3306': Can't connect to MySQL server on 'db6-lt.com:3306' (111)'
Would you like to remove it from the cluster's metadata? [y/N]: y

Could not open a connection to 'db7-lt.com:3306': 'MySQL Error 2003: Could not open connection to 'db7-lt.com:3306': Can't connect to MySQL server on 'db7-lt.com:3306' (111)'
Would you like to remove it from the cluster's metadata? [y/N]: y

NOTE: The instance 'localhost:3306' is running auto-rejoin process, which will be cancelled.

NOTE: Cancelling active GR auto-initialization at db8-lt.com:3306
db8-lt.com:3306 was restored.
The cluster was successfully rebooted.

<Cluster:UAT>
 MySQL  localhost:33060+ ssl  JS > cluster = dba.getCluster()
<Cluster:UAT>
 MySQL  localhost:33060+ ssl  JS > c.status()
{
    "clusterName": "UAT",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db8-lt.com:3306",
        "ssl": "REQUIRED",
        "status": "OK_NO_TOLERANCE",
        "statusText": "Cluster is NOT tolerant to any failures.",
        "topology": {
            "db8-lt.com:3306": {
                "address": "db8-lt.com:3306",
                "memberRole": "PRIMARY",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.26"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "db8-lt.com:3306"
}

3. После этого восстанавливаем реплики и делаем cluster.rescan()