除了内置的异步复制外,MySQL 5.7 还支持由插件实现的半同步复制接口。本节讨论什么是半同步复制及其工作原理。以下部分介绍了半同步复制的管理界面以及如何安装、配置和监控它。
MySQL 复制默认是异步的。源将事件写入其二进制日志,副本在准备就绪时请求它们。源不知道副本是否或何时检索并处理了事务,并且不能保证任何事件都会到达任何副本。对于异步复制,如果源崩溃,它提交的事务可能还没有传输到任何副本。在这种情况下,从源到副本的故障转移可能会导致故障转移到缺少与源相关的事务的服务器。
对于完全同步复制,当源提交事务时,所有副本也必须在源返回到执行事务的会话之前提交事务。完全同步复制意味着随时可以从源故障转移到任何副本。完全同步复制的缺点是完成事务可能会有很多延迟。
半同步复制介于异步和完全同步复制之间。源等待直到至少一个副本已接收并记录事件(所需的副本数是可配置的),然后提交事务。源不等待所有副本确认接收,它只需要来自副本的确认,而不是事件已在副本端完全执行和提交。因此,半同步复制保证如果源崩溃,它提交的所有事务都已传输到至少一个副本。
与异步复制相比,半同步复制提供了改进的数据完整性,因为当提交成功返回时,已知数据至少存在于两个地方。在半同步源收到来自所需数量的副本的确认之前,事务将暂停且不会提交。
与完全同步复制相比,半同步复制更快,因为它可以配置为平衡您对数据完整性的要求(确认收到事务的副本数)和提交速度,由于需要等待,提交速度较慢副本。
对于半同步复制,如果源崩溃并执行到副本的故障转移,则故障源不应该被重新用作复制源服务器,并且应该被丢弃。它可能有未被任何副本确认的事务,因此在故障转移之前未提交。
如果您的目标是实现容错复制拓扑,其中所有服务器以相同顺序接收相同事务,并且崩溃的服务器可以重新加入组并自动更新,您可以使用组复制来实现此目的. 有关信息,请参阅 第 17 章,组复制。
与异步复制相比,半同步复制的性能影响是提高数据完整性的权衡。减速量至少是将提交发送到副本并等待副本确认接收的 TCP/IP 往返时间。这意味着半同步复制最适合通过快速网络进行通信的近距离服务器,而最不适合通过慢速网络进行通信的远程服务器。半同步复制还通过限制二进制日志事件从源发送到副本的速度来限制繁忙会话的速率。当一个用户太忙时,这会减慢速度,这在某些部署情况下很有用。
源与其副本之间的半同步复制操作如下:
副本指示它在连接到源时是否具有半同步能力。
如果在源端启用了半同步复制并且至少有一个半同步副本,则在源上执行事务提交的线程会阻塞并等待,直到至少一个半同步副本确认它已收到该事务的所有事件,或者直到发生超时。
只有在事件被写入其中继日志并刷新到磁盘后,副本才会确认收到事务事件。
如果在没有任何副本确认事务的情况下发生超时,则源恢复为异步复制。当至少一个半同步副本赶上时,源返回到半同步复制。
必须在源端和副本端启用半同步复制。如果在源上禁用半同步复制,或者在源上启用但没有副本,则源使用异步复制。
当源处于阻塞状态(等待来自副本的确认)时,它不会返回到执行事务的会话。当块结束时,源返回到会话,然后可以继续执行其他语句。此时,事务已在源端提交,并且其事件的接收已被至少一个副本确认。源在返回会话之前必须在每个事务中接收的副本确认数可以使用
rpl_semi_sync_master_wait_for_slave_count
系统变量进行配置,默认值为 1。
在写入二进制日志的回滚之后也会发生阻塞,回滚修改非事务表的事务时会发生这种情况。回滚的事务即使对事务表没有影响也会被记录下来,因为对非事务表的修改无法回滚,必须发送到副本。
对于不在事务上下文中出现的语句(即,当没有事务以
START
TRANSACTION
or
开始时SET autocommit =
0
),启用自动提交并且每个语句隐式提交。对于半同步复制,每个这样的语句的源块,就像它对显式事务提交所做的那样。
rpl_semi_sync_master_wait_point
系统变量控制半同步复制源在将状态返回给提交事务的客户端之前等待副本确认事务接收的时间点
。
这些值是允许的:
AFTER_SYNC
(默认):源将每个事务写入其二进制日志和副本,并将二进制日志同步到磁盘。同步后,源等待事务接收的副本确认。收到确认后,源将事务提交给存储引擎并将结果返回给客户端,然后客户端可以继续进行。AFTER_COMMIT
:源将每个事务写入其二进制日志和副本,同步二进制日志,并将事务提交给存储引擎。源在提交后等待事务接收的副本确认。收到确认后,源将结果返回给客户端,然后客户端可以继续。
这些设置的复制特征不同如下:
使用
AFTER_SYNC
,所有客户端同时看到提交的事务,这是在副本确认并提交到源上的存储引擎之后。因此,所有客户端都在源上看到相同的数据。在源发生故障的情况下,在源上提交的所有事务都已复制到副本(保存到其中继日志)。源意外退出和故障转移到副本是无损的,因为副本是最新的。如上所述,故障转移后不应重复使用源。
使用
AFTER_COMMIT
,发出事务的客户端只有在服务器提交到存储引擎并收到副本确认后才会获得返回状态。在提交之后和副本确认之前,其他客户端可以在提交客户端之前看到提交的事务。如果出现问题导致副本无法处理事务,那么在源意外退出并故障转移到副本的情况下,此类客户端可能会看到与他们在源上看到的数据相关的数据丢失。