有没有办法修复已停止与master数据库同步的读取副本?我已经在删除它并创建一个新的,因为我找不到这个答案,但如果它再次发生,我会很高兴。
该数据库是一个MySQL数据库,包含Innodb表。
MySQL复制背后的原理很简单:如果你从两个相同的数据集开始,每次更改一个,就更改另一个,那么这两个数据集将保持相同。MySQL复制就是这样工作的——你从两个完全相同的服务器开始,要么完全空白,要么其中一个是另一个的精确快照,而复制只是在两个服务器上执行相同的事情。
复制是通过二进制日志("binlog")完成的,该日志捕获对主文件的所有更改。在RDS中使用的标准MySQL异步复制中,副本有两个特定用途的线程,一个是连接到主机并从主机的binlog中捕获复制事件并将其写入名为中继日志的临时保存区域的I/O线程,另一个是从中继日志中读取并将更改应用于副本的SQL线程。
在副本上,查询SHOW SLAVE STATUS;
将告诉您这两个线程是否正在运行。如果它们正在运行,则副本是健康的,尽管它可能在主副本之后,正如您在该查询的输出中也可以找到的值Seconds_Behind_Master
所证明的那样。否则,您将发现遇到的错误,导致一个或其他线程停止。
理论上,MySQL副本永远不会失去同步,除非发生以下三种情况之一:
- 您做了一些不应该做的事情,使复制副本与主副本不一致——例如使复制副本可写,并写入到它
- MySQL源代码中存在导致不一致的错误
- 复制品在足够长的时间段内与主机断开连接,使得主机已经丢弃了复制品从未见过的一些复制事件
第一个问题将导致SQL线程停止,因为它试图应用无意义的更改——通常是删除不存在的行,更新不存在或不匹配的行,插入已经存在的行等。
第二个问题可能会导致IO线程或SQL线程出现问题,但这种情况应该很少发生。
最后一个问题将导致IO线程停止,因为它记得在主线程上停止的位置,如果此时主线程上没有可用的二进制日志文件,则它将陷入僵局。RDS应该通过在主机上保留日志来防止这种情况,直到所有托管副本都捕获了日志。
因此,一般的答案是,您可以修复MySQL读取副本,方法是根据复制SQL线程当前指向的中继日志中主机的状态,将其所有数据完全置于其应处于的状态。
这在RDS中有点棘手,因为您没有SUPER
权限,但这仍然是可能的。还
tl;dr:复制中断只是一个症状——你必须弄清楚实际问题是什么。
您需要能够确定出了什么问题,并采取措施加以纠正。问题是,当复制停止时,除非您非常清楚地了解到底发生了什么,否则您实际上并不知道复制副本上的情况可能有多糟糕。
回想一下上面提到的原则——从两个相同的数据集开始,每次更改一个,就更改另一个——接下来需要注意的是,MySQL没有任何内置机制来确保在没有实际复制错误的情况下的一致性。两个服务器可能会有很大的差异,但复制将愉快地继续,直到SQL线程遇到无法复制的东西。您需要一个第三方实用程序,它可以比较两台服务器上的数据并指出任何差异。
如果您清楚地了解出了什么问题,可以暂时使复制副本可写(使用read_only
系统变量的参数组设置),进行更正更改,然后重新启动复制。在RDS上,由于您没有SUPER
权限,您只能通过重新启动副本在当前事件指针处重新启动,或者您可以在复制有问题的事件后将副本恢复到的状态,然后使用他们提供的解决方法,使用CALL mysql.rds_skip_repl_error();
在不了解其作用的情况下,请勿使用此--特别是,它会忽略故障并转移到下一个事件,这绝对会使您的复制副本处于不一致的状态,除非您手动使复制副本保持一致。当保持副本的最新状态比保持副本的正确性更重要时,应该只为紧急情况保留它,因为跳过错误本质上保证了将来会出现更多错误。
修复复制副本不是一件小事。这是一项经验丰富的DBA的任务。在RDS中,最好的选择通常是丢弃副本并创建一个新的副本,但由于复制错误永远不会发生——这不是你应该做的事情。如果你这样做了,你需要找出原因。