介绍

除了内置的异步复制之外,MySQL 5.7 还支持通过插件实现的半同步复制接口。本节讨论半同步复制的概念及其工作原理。接下来的部分将涵盖与半同步复制相关的管理界面,以及如何安装、配置和监控它。

异步复制

MySQL 复制默认是异步的。源服务器将事件写入其二进制日志,而复制服务器在准备好时请求这些事件。源服务器不知道复制服务器是否已检索和处理了事务,也无法保证任何事件是否曾到达任何复制服务器。在异步复制中,如果源服务器崩溃,已提交的事务可能尚未传输到任何复制服务器。在这种情况下,从源服务器切换到复制服务器可能导致切换到相对于源服务器缺失事务的服务器。

完全同步复制

在完全同步复制中,当源服务器提交一个事务时,所有复制服务器必须在源服务器返回到执行事务的会话之前也提交该事务。完全同步复制意味着可以随时从源服务器切换到任何复制服务器。完全同步复制的缺点是可能会有很大的延迟来完成一个事务。

半同步复制

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

三种复制方式对比

与异步复制相比,半同步复制提供了更高的数据完整性,因为当提交成功返回时,我们知道数据存在于至少两个位置。在半同步源服务器收到所需数量的复制服务器确认之前,事务将暂停并未提交。

与完全同步复制相比,半同步复制更快,因为它可以配置以平衡数据完整性的要求(确认事务接收的复制服务器数量)与提交速度之间的关系,而提交速度较慢是因为需要等待复制服务器。

与异步复制相比,半同步复制对性能的影响是为了提高数据完整性而进行的权衡。减慢的程度至少等于将提交发送到复制服务器并等待复制服务器确认接收的 TCP/IP 往返时间。这意味着半同步复制在快速网络上进行通信的紧密服务器之间效果最佳,而在慢速网络上进行通信的远程服务器之间效果最差。半同步复制还通过限制从源服务器到复制服务器发送二进制日志事件的速度,对繁忙会话进行了速率限制。当某个用户过于繁忙时,这会减缓其速度,在某些部署情况下可能会很有用。

半同步复制在源服务器和其复制服务器之间的操作如下:

  1. 当复制服务器连接到源服务器时,复制服务器指示其是否支持半同步。

  2. 如果源服务器启用了半同步复制并且至少有一个半同步复制的复制服务器,执行在源服务器上进行的事务提交的线程将被阻塞,并等待至少一个半同步复制的复制服务器确认已接收该事务的所有事件,或者直到发生超时。

  3. 复制服务器确认接收事务的事件仅在事件已写入其中继日志并刷新到磁盘后才会发生。

  4. 如果发生超时而没有任何复制服务器确认事务,则源服务器将回退到异步复制。当至少一个半同步复制的复制服务器赶上时,源服务器将返回到半同步复制。

  5. 半同步复制必须在源服务器和复制服务器的两端启用。如果源服务器上禁用了半同步复制,或者在源服务器上启用了半同步复制但没有任何复制服务器启用,则源服务器将使用异步复制。

在源服务器阻塞时(等待来自复制服务器的确认),它不会返回给执行事务的会话。当阻塞结束时,源服务器将返回给会话,然后会话可以继续执行其他语句。此时,事务在源服务器上已提交,并且至少一个复制服务器已确认接收其事件。在源服务器返回给会话之前,必须配置源服务器在每个事务中接收的复制服务器确认的数量。这可以使用 rpl_semi_sync_master_wait_for_slave_count 系统变量进行配置,其默认值为 1。

阻塞还会在写入二进制日志后进行回滚时发生,这发生在回滚修改非事务表的事务时。即使对于事务表而言回滚的事务没有效果,由于无法回滚非事务表的修改,因此已回滚的事务仍被记录并必须发送到复制服务器。

对于不在事务上下文中发生的语句(即未使用 START TRANSACTIONSET autocommit = 0 启动事务的语句),自动提交是启用的,每个语句都隐式提交。使用半同步复制时,源服务器为每个这样的语句阻塞,就像对于显式事务提交一样。

rpl_semi_sync_master_wait_point 系统变量控制在源服务器等待复制服务器确认事务接收后,返回给已提交事务的客户端状态的时间点。该变量可以配置为以下值:

  1. AFTER_SYNC(默认值):

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

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

这些设置的复制特性有以下不同:

  • 对于 AFTER_SYNC,所有客户端在相同的时间点看到已提交的事务,即在复制服务器确认并在源服务器上提交到存储引擎后。因此,所有客户端在源服务器上看到相同的数据。

  • 在源服务器失败的情况下,已在源服务器上提交的所有事务都已被复制到复制服务器(保存在其中继日志中)。源服务器的意外退出并切换到复制服务器是无损失的,因为复制服务器是最新的。如上所述,在切换后不应重新使用源服务器。

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

  • 如果发生故障,导致复制服务器未处理事务,则在源服务器意外退出并切换到复制服务器时,这些客户端可能看到与它们在源服务器上看到的数据不一致。

两个插件实现半同步功能:

  • 源端有一个插件,复制端也有一个插件。

系统变量

  • rpl_semi_sync_master_enabled:控制源端是否启用半同步复制。要启用或禁用插件,请将此变量分别设置为 1 或 0。默认值为 0(关闭)。
  • rpl_semi_sync_master_timeout:以毫秒为单位的数值,控制源端在提交时等待从复制服务器收到确认的超时时间,超时后将回退到异步复制。默认值为 10000(10 秒)。
  • rpl_semi_sync_slave_enabled:类似于 rpl_semi_sync_master_enabled,但控制复制端插件。

所有 rpl_semi_sync_xxx 系统变量的描述可参考《MySQL 5.7 Reference Manual》中的 Section 16.1.6.2 和 Section 16.1.6.3。

状态变量

  • Rpl_semi_sync_master_clients:半同步复制的复制服务器数量。
  • Rpl_semi_sync_master_status:源端当前是否在运行半同步复制。如果插件已启用且提交确认尚未发生,则值为 1。如果插件未启用或源端由于提交确认超时而回退到异步复制,则值为 0。
  • Rpl_semi_sync_master_no_tx:未被复制服务器成功确认的提交次数。
  • Rpl_semi_sync_master_yes_tx:被复制服务器成功确认的提交次数。
  • Rpl_semi_sync_slave_status:复制端当前是否在运行半同步复制。如果插件已启用且复制 I/O 线程正在运行,则值为 1。否则,值为 0。

所有 Rpl_semi_sync_xxx 状态变量的描述可参考《MySQL 5.7 Reference Manual》中的 Section 5.1.9。

从 MySQL 5.7.33 版本开始,可以通过启用以下系统变量来提高半同步复制的性能:

  • replication_sender_observe_commit_only:限制回调次数。
  • replication_optimize_for_static_plugin_config:添加共享锁并避免不必要的锁获取。这些设置在复制服务器数量增加时非常有帮助,因为锁的争用可能会降低性能。半同步复制源服务器也可以通过启用这些系统变量来获得性能优势,因为它们使用与复制服务器相同的锁定机制。

安装配置

半同步复制是通过插件实现的,因此必须将插件安装到服务器中以使其可用。安装插件后,可以通过与之关联的系统变量来控制插件。在关联的插件安装之前,这些系统变量是不可用的。

以下是安装半同步复制插件的步骤。有关安装插件的一般信息,请参阅《MySQL 5.7 Reference Manual》中的 Section 5.5.1。

要使用半同步复制,必须满足以下要求:

  1. 安装插件的能力需要支持动态加载的 MySQL 服务器。要进行验证,请检查 have_dynamic_loading 系统变量的值是否为 YES。二进制发行版应该支持动态加载。

  2. 复制必须已经在工作中,参见 Section 16.1。

  3. 不得配置多个复制通道。半同步复制仅兼容默认的复制通道。参见 Section 16.2.2。

为了设置半同步复制,请按照以下说明进行。此处提到的 INSTALL PLUGINSET GLOBALSTOP SLAVESTART SLAVE 语句需要 SUPER 权限。

MySQL 发行版包括源端和复制端的半同步复制插件文件。

为了被源端或复制端服务器使用,必须将相应的插件库文件放置在 MySQL 插件目录中(由 plugin_dir 系统变量指定的目录)。如果需要,可以通过在服务器启动时设置 plugin_dir 的值来配置插件目录位置。

插件库文件的基本名称为 semisync_mastersemisync_slave。文件名后缀因平台而异(例如,Unix 和类似 Unix 系统的为 .so,Windows 为 .dll)。

源端插件库文件必须存在于源服务器的插件目录中。复制端插件库文件必须存在于每个复制服务器的插件目录中。

要加载插件,请在源端和每个要使用半同步复制的复制端上使用 INSTALL PLUGIN 语句,根据需要调整平台的 .so 后缀。

在每个实例上都安装master 和 slave的插件

是为了防止集群拓扑结构发生变化后,实例角色变化。

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

查看插件

要查看已安装的插件,可以使用 SHOW PLUGINS 语句,或者查询信息模式的 PLUGINS 表。

show PLUGINs;SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';

只安装从服务器插件

# 只装 从服务器的 插件INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';# 查看参数show variables like '%rpl_semi_sync%';+---------------------------------+-------+| Variable_name | Value |+---------------------------------+-------+| rpl_semi_sync_slave_enabled | OFF || rpl_semi_sync_slave_trace_level | 32|+---------------------------------+-------+2 rows in set (0.00 sec)# 查看状态SHOW STATUS LIKE 'Rpl_semi_sync%';+----------------------------+-------+| Variable_name| Value |+----------------------------+-------+| Rpl_semi_sync_slave_status | OFF |+----------------------------+-------+1 row in set (0.00 sec)

只装主库插件

# 只装 主服务器的插件 INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';# 查看参数show variables like '%rpl_semi_sync%';+-------------------------------------------+------------+| Variable_name | Value|+-------------------------------------------+------------+| rpl_semi_sync_master_enabled| OFF|| rpl_semi_sync_master_timeout| 10000|| rpl_semi_sync_master_trace_level| 32 || rpl_semi_sync_master_wait_for_slave_count | 1|| rpl_semi_sync_master_wait_no_slave| ON || rpl_semi_sync_master_wait_point | AFTER_SYNC |+-------------------------------------------+------------+# 查看状态SHOW STATUS LIKE 'Rpl_semi_sync%';+--------------------------------------------+-------+| Variable_name| Value |+--------------------------------------------+-------+| Rpl_semi_sync_master_clients | 0 || Rpl_semi_sync_master_net_avg_wait_time | 0 || Rpl_semi_sync_master_net_wait_time | 0 || Rpl_semi_sync_master_net_waits | 0 || Rpl_semi_sync_master_no_times| 0 || Rpl_semi_sync_master_no_tx | 0 || Rpl_semi_sync_master_status| OFF || Rpl_semi_sync_master_timefunc_failures | 0 || Rpl_semi_sync_master_tx_avg_wait_time| 0 || Rpl_semi_sync_master_tx_wait_time| 0 || Rpl_semi_sync_master_tx_waits| 0 || Rpl_semi_sync_master_wait_pos_backtraverse | 0 || Rpl_semi_sync_master_wait_sessions | 0 || Rpl_semi_sync_master_yes_tx| 0 |+--------------------------------------------+-------+14 rows in set (0.01 sec)

命令行中设置变量

在安装了半同步复制插件之后,默认情况下它是禁用的。为了启用半同步复制,必须在源端和复制端都启用插件。如果只有一侧启用,复制将是异步的。

要控制已安装插件是否启用,请设置相应的系统变量。可以使用 SET GLOBAL 在运行时设置这些变量,也可以在命令行上或在选项文件中在服务器启动时设置。

在运行时,可以使用以下源端系统变量:

SET GLOBAL rpl_semi_sync_master_enabled = {0|1};SET GLOBAL rpl_semi_sync_master_timeout = N;

在复制端 设置系统变量 :

SET GLOBAL rpl_semi_sync_slave_enabled = {0|1};

对于 rpl_semi_sync_master_enabledrpl_semi_sync_slave_enabled,值应设置为 1 以启用半同步复制,或设置为 0 以禁用它。默认情况下,这些变量的值设置为 0。

对于 rpl_semi_sync_master_timeout,给定的值 N 表示毫秒。默认值为 10000(10 秒)。

如果在运行时在复制端启用半同步复制,还必须启动(如果它已经在运行则首先停止)复制 I/O 线程,以使复制端连接到源端并注册为半同步复制的复制服务器:

-- 在复制端启用半同步复制SET GLOBAL rpl_semi_sync_slave_enabled = 1;-- 如果复制 I/O 线程正在运行,则停止它STOP SLAVE IO_THREAD;-- 启动复制 I/O 线程START SLAVE IO_THREAD;

如果复制 I/O 线程已经在运行且您不重新启动它,复制服务器将继续使用异步复制。

配置文件中设置

在服务器启动时,可以将控制半同步复制的变量设置为命令行选项或选项文件中。在选项文件中列出的设置将在每次服务器启动时生效。例如,可以在源端和复制端的 my.cnf 文件中如下设置这些变量。

在源端:

[mysqld]rpl_semi_sync_master_enabled=1rpl_semi_sync_master_timeout=1000 # 1 秒

在每个复制端:

[mysqld]rpl_semi_sync_slave_enabled=1

这样设置后,需要重新启动 MySQL 服务器才能使更改生效。

半同步复制监控

半同步复制功能的插件公开了多个系统变量和状态变量,您可以检查它们以确定其配置和操作状态。

系统变量反映了半同步复制的配置。要检查它们的值,请使用 SHOW VARIABLES

mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';

状态变量使您能够监视半同步复制的操作。要检查它们的值,请使用 SHOW STATUS

SHOW STATUS LIKE 'Rpl_semi_sync%';

当源端由于提交阻塞超时或复制服务器赶上而在异步和半同步之间切换时,它会相应地设置 Rpl_semi_sync_master_status 状态变量的值。源端从半同步回退到异步复制意味着即使在某一时刻半同步复制实际上不可操作,rpl_semi_sync_master_enabled 系统变量在源端仍然可能具有值为 1。您可以监视 Rpl_semi_sync_master_status 状态变量以确定源端当前是使用异步还是半同步复制。

要查看连接的半同步复制副本数量,请检查 Rpl_semi_sync_master_clients

Rpl_semi_sync_master_yes_txRpl_semi_sync_master_no_tx 变量指示了已被复制服务器成功或不成功确认的提交次数。

在复制端,Rpl_semi_sync_slave_status 表示半同步复制当前是否在运行。

参数变量

  1. rpl_semi_sync_master_enabled:

    • 描述:控制是否在源端启用半同步复制。要启用或禁用插件,请将此变量设置为 ON 或 OFF(或 1 或 0)。默认值为 OFF。
    • 注意:仅在源端安装了半同步复制插件时才可用。
  2. rpl_semi_sync_master_timeout:

    • 描述:控制源端在等待复制服务器回复的超时时间(以毫秒为单位)。默认值为 10000(10秒)。
    • 注意:仅在源端安装了半同步复制插件时才可用。
  3. rpl_semi_sync_master_trace_level:

    • 描述:源端上的半同步复制调试追踪级别。定义了四个级别:
      • 1 = 一般级别(例如,时间函数失败)
      • 16 = 详细级别(更详细的信息)
      • 32 = 网络等待级别(关于网络等待的更多信息)
      • 64 = 函数级别(关于函数进入和退出的信息)
    • 注意:仅在源端安装了半同步复制插件时才可用。
  4. rpl_semi_sync_master_wait_for_slave_count:

    • 描述:源端在每个事务之前必须收到的复制服务器确认的数量。默认情况下,rpl_semi_sync_master_wait_for_slave_count 为 1,意味着在收到单个复制服务器确认后,半同步复制会继续进行。此变量的小值可获得更好的性能。
    • 示例:如果 rpl_semi_sync_master_wait_for_slave_count 为 2,则必须在半同步复制继续进行之前收到 2 个复制服务器对事务的确认。如果在超时期间内少于 2 个复制服务器对事务的确认,源端将回退到正常复制。
    • 注意:仅在源端安装了半同步复制插件时才可用。
  5. rpl_semi_sync_master_wait_no_slave:

    • 描述:控制源端是否等待 rpl_semi_sync_master_timeout 到期,即使在超时期间复制服务器的数量降至少于 rpl_semi_sync_master_wait_for_slave_count。当 rpl_semi_sync_master_wait_no_slave 的值为 ON(默认情况下)时,允许在超时期间复制服务器的数量降至少于 rpl_semi_sync_master_wait_for_slave_count。只要足够的复制服务器在超时期满前对事务进行确认,半同步复制就会继续进行。当 rpl_semi_sync_master_wait_no_slave 的值为 OFF 时,如果在 rpl_semi_sync_master_timeout 配置的超时期间内复制服务器的数量降至少于 rpl_semi_sync_master_wait_for_slave_count,源端将回退到正常复制。
    • 注意:仅在源端安装了半同步复制插件时才可用。
  6. rpl_semi_sync_master_wait_point

这个变量控制半同步源在返回提交事务的客户端状态之前等待复制确认的时间点。可以使用以下值:

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

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

这些设置的复制特性有以下不同:

  • 对于 AFTER_SYNC,所有客户端同时看到提交的事务:在复制服务器确认并在源端提交到存储引擎之后。因此,所有客户端在源上看到相同的数据。

    在源故障的情况下,所有在源上提交的事务已经复制到了复制服务器(保存在其中继日志中)。源的意外退出和切换到复制服务器是无损的,因为复制服务器是最新的。但请注意,在这种情况下无法重新启动源,必须放弃源,因为其二进制日志可能包含未提交的事务,在二进制日志恢复后,这可能会导致与复制服务器的冲突。

  • 对于 AFTER_COMMIT,发出事务的客户端仅在服务器提交到存储引擎并收到复制服务器确认后才获得返回状态。在提交后和复制服务器确认之前,其他客户端可以在提交客户端之前看到提交的事务。

如果出现问题,例如复制服务器未处理事务,在源端意外退出并切换到复制服务器的情况下,这可能导致这些客户端相对于在源上看到的数据出现数据丢失。

此变量仅在源端安装了半同步复制插件时才可用。

rpl_semi_sync_master_wait_point 在 MySQL 5.7.2 中添加。对于较旧的版本,半同步源的行为等同于 AFTER_COMMIT 的设置。

此更改引入了版本兼容性约束,因为它增加了半同步接口版本:MySQL 5.7.2 及更高版本的服务器不能与旧版本的半同步复制插件一起使用,反之亦然。

状态变量

这些是半同步复制功能的插件暴露的一些系统和状态变量,用于确定其配置和操作状态:

  • Rpl_semi_sync_master_clients: 半同步复制副本的数量。

  • Rpl_semi_sync_master_net_avg_wait_time: 源端等待复制服务器回复的平均时间(微秒)。此变量已被弃用,始终为 0;预计在将来的版本中移除。

  • Rpl_semi_sync_master_net_wait_time: 源端等待复制服务器回复的总时间(微秒)。此变量已被弃用,始终为 0;预计在将来的版本中移除。

  • Rpl_semi_sync_master_net_waits: 源端等待复制服务器回复的总次数。

  • Rpl_semi_sync_master_no_times: 源端关闭半同步复制的次数。

  • Rpl_semi_sync_master_no_tx: 未被复制服务器成功确认的提交次数。

  • Rpl_semi_sync_master_status: 源端当前是否在运行半同步复制。如果启用了插件并且提交确认已发生,则值为 ON。如果未启用插件或源端由于提交确认超时而回退到异步复制,则值为 OFF。

  • Rpl_semi_sync_master_timefunc_failures: 源端调用时间函数(例如 gettimeofday())失败的次数。

  • Rpl_semi_sync_master_tx_avg_wait_time: 源端等待每个事务的平均时间(微秒)。

  • Rpl_semi_sync_master_tx_wait_time: 源端等待事务的总时间(微秒)。

  • Rpl_semi_sync_master_tx_waits: 源端等待事务的总次数。

  • Rpl_semi_sync_master_wait_pos_backtraverse: 源端等待事件的总次数,其二进制坐标低于先前等待的事件。当事务开始等待回复的顺序与它们的二进制日志事件写入的顺序不同时,就会发生这种情况。

  • Rpl_semi_sync_master_wait_sessions: 当前等待复制服务器回复的会话数。

  • Rpl_semi_sync_master_yes_tx: 被复制服务器成功确认的提交次数。

  • Rpl_semi_sync_slave_status: 复制端当前是否在运行半同步复制。如果启用了插件且复制 I/O 线程正在运行,则值为 ON。否则,值为 OFF。