16.3.9 半同步复制

除了内置的异步复制之外,MySQL 5.7 还支持通过插件实现的半同步复制接口。本节讨论什么是半同步复制及其工作方式。以下各节介绍了半同步复制的 Management 界面以及如何安装,配置和监视它。

默认情况下,MySQL 复制是异步的。源将事件写入其二进制日志,副本将在事件就绪时请求它们。源不知道副本是否或何时检索和处理了事务,并且不能保证任何事件都会到达任何副本。使用异步复制,如果源崩溃,则它提交的事务可能不会传输到任何副本。在这种情况下,从源到副本的故障转移可能会导致故障转移到缺少相对于源的事务的服务器。

对于完全同步复制,当源提交事务时,所有副本也必须已提交事务,然后源才返回执行事务的会话。完全同步复制意味着可以随时从源故障转移到任何副本。完全同步复制的缺点是完成事务可能会有很多延迟。

半同步复制介于异步复制和完全同步复制之间。源 await 直到至少一个副本接收并记录了事件(所需的副本数量是可配置的),然后提交事务。源不 await 所有副本都确认收到,它仅需要副本的确认,而不是事件已在副本端完全执行并提交。因此,半同步复制可确保如果源崩溃,则它已提交的所有事务都已传输到至少一个副本。

与异步复制相比,半同步复制提供了改进的数据完整性,因为众所周知,当提交成功返回时,数据至少存在两个位置。在半同步源收到所需数量的副本的确认之前,该事务处于保留状态且未提交。

与完全同步复制相比,半同步复制更快,因为半同步复制可以配置为平衡数据完整性要求(确认已收到事务的副本数量)和提交速度,提交速度由于需要 await 而较慢副本。

Important

使用半同步复制时,如果源崩溃并且执行了对副本的故障转移,则不应将发生故障的源用作复制源服务器,而应将其丢弃。它可能具有任何副本都未确认的事务,因此在故障转移之前未提交这些事务。

如果您的目标是实施容错复制拓扑,其中所有服务器以相同的 Sequences 接收相同的事务,并且崩溃的服务器可以重新加入组并自动更新,则可以使用组复制来实现此目的。 。有关信息,请参阅第 17 章,组复制

与异步复制相比,半同步复制对性能的影响是增加数据完整性的权衡。减速量至少是 TCP/IP 往返时间,以将提交发送到副本并 await 副本确认接收。这意味着半同步复制最适合通过快速网络通信的关闭服务器,而最不适合通过慢速网络通信的远程服务器。半同步复制还通过限制二进制日志事件从源发送到副本的速度,对繁忙的会话设置了速率限制。当一个用户太忙时,这会减慢速度,这在某些部署情况下很有用。

源及其副本之间的半同步复制操作如下:

  • 副本 table 示连接到源时是否具有半同步功能。

  • 如果在源端启用了半同步复制,并且至少有一个半同步副本,则在源块上执行事务提交的线程将 await,直到至少一个半同步副本确认已接收到该事务的所有事件为止,或者直到发生超时。

  • 仅在事件已被写入其中继日志并刷新到磁盘之后,副本才确认收到事务事件。

  • 如果在没有任何副本确认事务的情况下发生超时,则源将恢复为异步复制。赶上至少一个半同步副本时,源将返回到半同步复制。

  • 必须在源端和副本端都启用半同步复制。如果在源上禁用了半同步复制,或者在源上启用了半同步复制但没有任何副本,则源使用异步复制。

当源处于阻塞状态(await 来自副本的确认)时,它不会返回执行该事务的会话。当该块结束时,源将返回到会话,然后该会话可以 continue 执行其他语句。至此,事务已在源端进行了提交,并且至少一个副本已确认其事件的接收。源可以使用rpl_semi_sync_master_wait_for_slave_count系统变量(默认值为 1)配置在返回会话之前源必须在每个事务中收到的副本确认的数量。

在回写到二进制日志的回滚之后也会发生阻塞,回滚会在修改非事务 table 的事务回滚时发生。即使回滚的事务对事务 table 没有影响,也会记录回滚的事务,因为对非事务 table 的修改无法回滚,必须将其发送到副本。

对于不在事务上下文中发生的语句(即,当没有使用START TRANSACTIONSET 自动提交= 0启动任何事务时),将启用自动提交功能,并且每个语句都将隐式提交。使用半同步复制,源将阻止每个此类语句,就像显式事务提交一样。

rpl_semi_sync_master_wait_point系统变量控制半同步复制源在将状态返回给提交事务的 Client 端之前 await 事务接收的副本确认的时间点。这些值是允许的:

  • AFTER_SYNC(默认值):源将每个事务写入其二进制日志和副本,并将二进制日志同步到磁盘。同步后,源 awaitTransaction 收据的副本确认。收到确认后,源将事务提交到存储引擎,然后将结果返回给 Client 端,然后 Client 端可以 continue 进行。

  • AFTER_COMMIT:源将每个事务写入其二进制日志和副本,同步二进制日志,然后将事务提交到存储引擎。提交后,源将 await 事务接收的副本确认。收到确认后,源将结果返回给 Client 端,然后 Client 端可以 continue 进行。

这些设置的复制 Feature 不同,如下所示:

  • 使用AFTER_SYNC,所有 Client 端将同时看到已提交的事务,这是副本已确认该事务并将其提交到源上的存储引擎之后。因此,所有 Client 端都在源上看到相同的数据。

如果发生源故障,则已将在源上提交的所有事务复制到副本(保存到其中继日志)。源的崩溃和到副本的故障转移是无损的,因为副本是最新的。如上所述,故障转移后不应重用源。

  • 使用AFTER_COMMIT,发出事务的 Client 端仅在服务器提交到存储引擎并收到副本确认后才获得返回状态。在提交之后和副本确认之前,其他 Client 端可以在提交 Client 端之前看到提交的事务。

如果出现问题,导致副本无法处理事务,则在源崩溃和故障转移到副本的情况下,此类 Client 端可能会看到相对于其在源上看到的数据丢失的数据。