MySQL Shell 8.4  /  ...  /  InnoDB ClusterSet 集群中不一致的事务集(GTID 集)

8.9.2 InnoDB ClusterSet 集群中不一致的事务集(GTID 集)

如果 InnoDB Cluster 的 GTID 集与 InnoDB ClusterSet 中主集群上的 GTID 集不一致,AdminAPI 的 clusterSet.status() 命令会发出警告。处于此状态的集群与 InnoDB ClusterSet 中的其他集群相比,具有额外的事务,并且具有全局状态 OK_NOT_CONSISTENT。集群在此状态下继续在 InnoDB ClusterSet 中运行,如果其 GTID 集是可用的副本集群中最新的,则您可以对其执行紧急故障转移。但是,它不符合受控切换的条件,因为事务差异可能会导致客户端访问错误的数据。如果集群离线,它也不能使用额外的事务重新加入 InnoDB ClusterSet。

InnoDB ClusterSet 中的副本集群是只读的,因此如果它始终是副本集群,则它不应包含额外的事务,除非在未使用 AdminAPI 命令的情况下对集群进行了更改。如果您需要在停止组复制时对实例执行管理事务,请务必在发出管理语句之前将 sql_log_bin 系统变量的值设置为 OFF,并在之后将其设置回 ON

Press CTRL+C to copy
SET SQL_LOG_BIN=0; <administrator action> SET SQL_LOG_BIN=1;

将此系统变量设置为 OFF 意味着从该时间点到您将其设置回 ON 期间发生的事务不会写入二进制日志,并且不会为其分配 GTID。

一种可能在没有外部更改的情况下创建不同事务集的情况是,当主集群无法访问并且使用了紧急故障转移过程时。如果主集群在故障转移后保持在线,它可以通过任何仍然连接到它的 MySQL Router 实例继续接受来自客户端的事务,并将这些事务传递给仍然连接到它的任何副本集群。或者,严重的复制延迟可能会导致选择作为替换主集群的副本集群缺少来自主集群的一些事务。在这种情况下,当旧的主集群最初作为无效的副本集群重新上线时,从未传输到副本的事务将被识别为额外的事务。

clusterSet.status() 命令的扩展输出标识了任何具有额外事务的集群,并为其分配了 OK_NOT_CONSISTENT 全局状态。例如

Press CTRL+C to copy
mysql-js> myclusterset.status({extended: 1}) { "clusters": { "clusterone": { "clusterErrors": [ "ERROR: Errant transactions detected" ], "clusterRole": "REPLICA", "clusterSetReplication": { "applierStatus": "APPLIED_ALL", "applierThreadState": "Waiting for an event from Coordinator", "applierWorkerThreads": 4, "receiver": "127.0.0.1:3310", "receiverStatus": "ON", "receiverThreadState": "Waiting for source to send event", "source": "127.0.0.1:4410" }, "clusterSetReplicationStatus": "OK", "globalStatus": "OK_NOT_CONSISTENT", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "127.0.0.1:3310": { "address": "127.0.0.1:3310", "memberRole": "PRIMARY", "mode": "R/O", "replicationLagFromImmediateSource": "", "replicationLagFromOriginalSource": "", "status": "ONLINE", "version": "8.0.27" }, "127.0.0.1:3320": { "address": "127.0.0.1:3320", "memberRole": "SECONDARY", "mode": "R/O", "replicationLagFromImmediateSource": "", "replicationLagFromOriginalSource": "", "status": "ONLINE", "version": "8.0.27" }, "127.0.0.1:3330": { "address": "127.0.0.1:3330", "memberRole": "SECONDARY", "mode": "R/O", "replicationLagFromImmediateSource": "", "replicationLagFromOriginalSource": "", "status": "ONLINE", "version": "8.0.27" } }, "transactionSet": "54ff337b-2ccf-11ec-95da-3c6aa7197deb:1-131,54ff3ed7-2ccf-11ec-95da-3c6aa7197deb:1-5,c06527d6-2ce3-11ec-a55e-3c6aa7197deb:1,c0653492-2ce3-11ec-a55e-3c6aa7197deb:1-5", "transactionSetConsistencyStatus": "INCONSISTENT", "transactionSetConsistencyStatusText": "There are 1 transactions that were executed in this instance that did not originate from the PRIMARY.", "transactionSetErrantGtidSet": "c06527d6-2ce3-11ec-a55e-3c6aa7197deb:1", "transactionSetMissingGtidSet": "" }, "clustertwo": { "clusterRole": "PRIMARY", "globalStatus": "OK", "primary": "127.0.0.1:4410", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "127.0.0.1:4410": { "address": "127.0.0.1:4410", "memberRole": "PRIMARY", "mode": "R/W", "status": "ONLINE", "version": "8.0.27" }, "127.0.0.1:4420": { "address": "127.0.0.1:4420", "memberRole": "SECONDARY", "mode": "R/O", "replicationLagFromImmediateSource": "", "replicationLagFromOriginalSource": "", "status": "ONLINE", "version": "8.0.27" }, "127.0.0.1:4430": { "address": "127.0.0.1:4430", "memberRole": "SECONDARY", "mode": "R/O", "replicationLagFromImmediateSource": "", "replicationLagFromOriginalSource": "", "status": "ONLINE", "version": "8.0.27" } }, "transactionSet": "54ff337b-2ccf-11ec-95da-3c6aa7197deb:1-131,54ff3ed7-2ccf-11ec-95da-3c6aa7197deb:1-5" } }, "domainName": "testclusterset", "globalPrimaryInstance": "127.0.0.1:4410", "metadataServer": "127.0.0.1:4410", "primaryCluster": "clustertwo", "status": "AVAILABLE", "statusText": "Primary Cluster available, there are issues with a Replica cluster." }

将单个服务器的数据与 InnoDB Cluster 的其余部分协调的最安全方法是,确定 InnoDB ClusterSet 部署中拥有最佳数据(最多事务、最新事务或最重要事务)的服务器,并使用 MySQL 的克隆功能将内容从该服务器传输到受影响的服务器。有关执行此操作的说明,请参阅 克隆远程数据。然后使用 cluster.rejoinInstance() 命令让实例重新加入 InnoDB Cluster。有关此操作的详细信息,请参阅 第 7.8.1 节 “将实例重新加入集群”

如果整个 InnoDB Cluster 都受到影响,请按照 第 8.9.4 节 “从 InnoDB ClusterSet 中移除集群” 中的过程从 InnoDB ClusterSet 部署中移除受影响的集群,并在其位置设置一个新的 InnoDB Cluster。新 InnoDB Cluster 中的服务器实例将在设置过程中接收正确的事务集。

如果您想保留额外的事务,可以执行紧急故障转移,按照 第 8.8 节 “InnoDB ClusterSet 紧急故障转移” 中的过程,使包含这些事务的 InnoDB Cluster 成为主集群。

如果您能够处理问题事务,请使用 clusterSet.rejoinCluster() 操作将 InnoDB Cluster 重新加入 InnoDB ClusterSet 部署。有关执行此操作的说明,请参阅 第 8.9.5 节 “将集群重新加入 InnoDB ClusterSet”