3.10半同步复制

除了内置的异步复制,MySQL 8.0还支持通过插件实现的半同步复制接口。本节讨论半同步复制是什么以及它是如何工作的。以下部分介绍了半同步复制的管理界面,以及如何安装、配置和监视它。

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

使用完全同步复制,当源提交事务时,所有副本也已在源返回执行事务的会话之前提交了事务。完全同步复制意味着可以在任何时候从源故障转移到任何副本。完全同步复制的缺点是完成事务可能会有很多延迟。

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

与异步复制相比,半同步复制提供了更好的数据完整性,因为当提交成功返回时,可以知道数据至少存在于两个位置。在半同步源从所需数量的副本接收到确认之前,事务处于暂停状态,不提交。

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

重要的

在使用半同步复制时,如果源崩溃,并且执行了向副本的故障转移,则不应将失败的源重用为复制源,而应丢弃。它可能具有不被任何副本确认的事务,因此在故障转移之前没有提交这些事务。

如果您的目标是实现一个容错复制拓扑,其中所有服务器以相同的顺序接收相同的事务,并且崩溃的服务器可以重新加入组并自动更新,那么您可以使用group replication来实现这一点。有关信息,请参见组复制

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

源和副本之间的半同步复制原理如下:

  • 副本在连接到源时指示它是否具有半同步能力。

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

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

  • 如果发生超时,但没有任何副本确认该事务,源将恢复到异步复制。当至少有一个半同步副本赶上时,源端将恢复半同步复制。

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

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

在写入二进制日志的回滚之后也会发生阻塞,当修改非事务性表的事务回滚时就会发生阻塞。回滚的事务被记录下来,即使它对事务性表没有影响,因为对非事务性表的修改不能回滚,必须发送到副本。

对于不在事务上下文中出现的语句(也就是说,当没有事务开始时)开始事务设置自动提交= 0),自动提交被启用,每个语句隐式提交。对于半同步复制,源块用于每个这样的语句,就像显式事务提交一样。

rpl_semi_sync_master_wait_point系统变量控制半同步源服务器在向提交事务的客户端返回状态之前等待事务接收的副本确认的时间点。这些值是允许的:

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

  • AFTER_COMMIT:源将每个事务写入其二进制日志和副本,同步二进制日志,并将事务提交给存储引擎。在提交之后,源等待事务接收的副本确认。在收到确认后,源将结果返回给客户端,然后客户端可以继续。

这些设置的复制特性如下所示:

  • AFTER_SYNC时,所有客户端同时看到已提交的事务,这是在它被副本确认并提交给源上的存储引擎之后。因此,所有客户端在源上看到相同的数据。

    在源故障的情况下,源上提交的所有事务都被复制到副本(保存到其中继日志中)。源的意外退出和故障转移到副本是无损的,因为副本是最新的。如上所述,在故障转移之后不应该重用源。

  • AFTER_COMMIT,发出事务的客户端只有在服务器提交到存储引擎并接收到副本确认后才能获得返回状态。在提交之后和副本确认之前,其他客户端可以在提交客户端之前看到已提交的事务。

    如果出现错误,副本不能处理事务,那么在意外的源退出和故障转移到副本的情况下,这样的客户端可能会看到相对于它们在源上看到的数据丢失。