4

有没有办法修复已停止与主数据库同步的只读副本?我已经在删除它并创建一个新的,因为我找不到这个答案,但很高兴知道它是否再次发生。

数据库是带有 Innodb 表的 MySQL 数据库。

4

1 回答 1

6

MySQL 复制背后的原理很简单:如果您从两个相同的数据集开始,并且每次更改其中一个,就更改另一个,那么这两个数据集将保持相同。这就是 MySQL 复制的工作原理——你从两台完全相同的服务器开始,或者完全空白,或者其中一台是另一台的精确快照,复制只是在两台服务器上执行相同的事情。

复制是通过二进制日志(“binlog”)完成的,它捕获对主节点的所有更改。在标准 MySQL 异步复制中——如在 RDS 中使用的——副本有两个特定用途的线程,连接到主服务器的 I/O 线程并从主服务器的 binlog 中捕获复制事件并将它们写入一个名为的临时保存区域中继日志,以及从中继日志读取并将更改应用于副本的 SQL 线程。

在副本上,查询SHOW SLAVE STATUS;将告诉您这两个线程是否正在运行。如果它们正在运行,则副本是健康的,尽管它可能在主服务器之后,正如Seconds_Behind_Master您还将在该查询的输出中找到的值所证明的那样。否则,您会发现已经遇到的错误,导致一个或其他线程停止。

理论上,除非发生以下三种情况之一,否则 MySQL 副本永远不会不同步:

  • 你做了一些你不应该做的事情,使副本与主副本不一致——例如使副本可写,然后写入它。
  • MySQL 源代码中存在导致不一致的错误
  • 副本与主节点断开连接的时间足够长,以至于主节点已经丢弃了一些副本从未见过的复制事件。

第一个问题将导致 SQL 线程停止,因为它试图应用无意义的更改——通常删除不存在的行、更新不存在或不匹配的行、插入已经存在的行, ETC。

第二个问题可能会导致 IO 线程或 SQL 线程出现问题,但这些问题应该很少见。

最后一个问题将导致 IO 线程停止,因为它会记住它在 master 上的中断位置,如果此时 master 上没有可用的二进制日志文件,则它处于僵局。RDS 应该通过在主服务器上保存日志直到所有托管副本都捕获它们来防止这种情况。

因此,一般的答案是,您可以修复 MySQL 只读副本,方法是根据复制 SQL 线程当前指向的时间点上的主服务器状态,将其所有数据完全恢复到它应该处于的状态, 在中继日志中。

这在 RDS 中有点棘手,因为您没有SUPER特权,但它仍然是可能的。仍然...

tl; dr:复制中断只是一种症状——你必须弄清楚实际问题是什么。

您需要能够识别出问题所在,并采取措施进行纠正。问题是,当复制停止时,除非您非常清楚地了解究竟发生了什么,否则您实际上并不知道副本上的情况可能有多糟糕。

回想上面提到的原理——从两个相同的数据集开始,每次更改一个,更改另一个——接下来要注意的是,MySQL 没有任何内置机制来确保在缺席时的一致性实际的复制错误。两台服务器可能有很大的不同,但复制会愉快地继续,直到 SQL 线程遇到它无法复制的东西。您需要一个可以比较两台服务器上的数据并找出任何差异的第三方实用程序。

如果您清楚地了解出了什么问题,您可以暂时使副本可写(使用read_only系统变量的参数组设置),进行更正更改,然后重新启动复制。在 RDS 上,您只能通过重新启动副本在当前事件指针处重新启动,因为您没有权限,或者您可以将副本恢复到复制有问题的事件SUPER应该处于的状态,然后使用他们为此提供了解决方法,使用. 不要使用这个CALL mysql.rds_skip_repl_error();不了解它的作用——具体来说,它会忽略故障并继续下一个事件,除非您手动使副本保持一致,否则绝对会使您的副本处于不一致的状态。它应该仅用于紧急情况,当保持副本当前比保持副本正确更重要时,因为跳过错误本质上保证了将来会出现更多错误。

修复复制品并非易事。这是有经验的 DBA 的任务。在 RDS 中,最好的选择通常是丢弃副本并创建一个新副本,但由于永远不会发生复制错误——这不是您应该做的事情。如果你这样做了,你需要找出原因。

于 2019-02-06T18:57:24.820 回答