MySQL 5.7 半同步复制

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

默认情况下,MySQL的复制是异步的。主服务器将事件写入其二进制日志,但不知道从服务器是否或何时检索并处理了这些事件。使用异步复制 时,如果主服务器崩溃,则它提交的事务可能没有传输到任何从服务器。因此,在这种情况下,从主服务器到从服务器的故障转移可能导致故障 转移到一个相对于主服务器缺少事务的服务器。

半同步复制可以作为异步复制的替代方案:
.从节点表示它连接到主节点时是否具有半同步能力

.如果在主端启用了半同步复制,并且至少有一个半同步从端,那么在主端执行事务提交的线程将阻塞并等待,直到至少一个半同步从端确认它 已接收到该事务的所有事件,或者直到超时发生。

.从属服务器只有在将事务事件写入其中继日志并刷新到磁盘后,才会确认接收到事务事件。

.如果超时发生,而从服务器没有确认事务,则主服务器恢复到异步复制。当至少有一个半同步从端赶上时,主端返回到半同步复制。

.必须在主端和从端同时启用半同步复制。如果在主端禁用了半同步复制,或者在主端启用了半同步复制,但没有从端,则主端使用异步复制

当主服务器阻塞(等待从服务器的确认)时,它不会返回到执行该事务的会话。当阻塞束时,主程序返回到会话,然后可以继续执行其他语句。 此时,事务已在主端提交,并且至少有一个从端已确认其事件的接收。

从MySQL 5.7.3开始,主服务器在处理每个事务之前必须接收的从服务器应答的数量可以使用rpl_semi_sync_master_wait_for_slave_count系统 变量进行配置。缺省值为1。

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

对于不在事务上下文中出现的语句(即,当没有使用START transaction或SET autocommit = 0启动事务时),启用自动提交,并且每个语句都 隐式提交。对于半同步复制,主程序阻塞每个这样的语句,就像它对显式事务提交所做的那样。

为了理解“半同步复制”中的“semi”是什么意思,将其与异步复制和全同步复制进行比较:
.使用异步复制,主服务器将事件写入其二进制日志,从服务器在准备好时请求事件。不能保证任何事件都会同步到任何一个从服务器。
.使用完全同步复制,当主服务器提交事务时,所有从服务器也将在主服务器返回到执行事务的会话之前提交该事务。这样做的缺点是完成事务 可能会有很多延迟。
.半同步复制介于异步复制和全同步复制之间。主服务器只等待至少一个从服务器接收并记录事件。它不等待所有从服务器确认接收,它只需要 接收,而不需要在从服务器端完全执行和提交事件。

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

半同步复制还通过限制二进制日志事件从主服务器发送到从服务器的速度,对繁忙会话设置了速率限制。当一个用户太忙时,这将降低其速度, 这在某些部署情况下很有用。

半同步复制确实有一些性能影响,因为由于需要等待从,提交速度较慢。这是为了提高数据完整性而进行的权衡。减慢的时间至少是TCP/IP往返 时间,从服务器发送提交到从服务器并等待从服务器确认接收。这意味着,对于通过快速网络通信的近距离服务器,半同步复制效果最好,而对 于通过慢速网络通信的远程服务器,效果最差。

rpl_semi_sync_master_wait_point系统变量控制半同步复制主服务器在向提交事务的客户机返回状态之前等待从服务器确认事务接收的时间点 。这些值是允许的:
.AFTER_SYNC(默认值):主服务器将每个事务写入其二进制日志和从服务器,并将二进制日志同步到磁盘。同步完成后,主服务器等待从服务器对 事务接收的确认。接收到确认后,主服务器将事务提交给存储引擎,并将结果返回给客户端,然后客户端就可以继续进行了。
.AFTER_COMMIT:主服务器将每个事务写入其二进制日志和从服务器,同步二进制日志,并将事务提交给存储引擎。在提交之后,主服务器等待从 服务器对事务接收的确认。接收到确认后,主服务器将结果返回给客户端,然后客户端可以继续进行。

这些设置的复制特性区别如下:
.使用AFTER_SYNC,所有客户端同时看到提交的事务:在它被从服务器确认并提交到主服务器上的存储引擎之后。因此,所有客户端都在主服务 器上看到相同的数据。
在主服务器发生故障时,主服务器上提交的所有事务都被复制到从服务器(保存到其中继日志中)。主服务器崩溃和故障转移到从服务器是无损 的,因为从服务器是最新的。

.使用AFTER_COMMIT,发出事务的客户端只有在服务器提交到存储引擎并收到从服务器的确认后才能获得返回状态。在提交之后,在slave确认之 前,其他客户端可以在提交之前看到已提交的事务。
如果出现问题,从服务器无法处理事务,那么在主服务器崩溃并故障转移到从服务器的情况下,这些客户端可能会看到相对于在主服务器上看到 的数据丢失。

半同步复制管理接口
半同步复制的管理接口有几个组件:
.两个插件实现了半同步功能。主端有一个插件,从端有一个插件。
.系统变量控制插件的行为。一些例子:
.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_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。

系统变量和状态变量只有在使用install plugin安装了适当的主插件或从插件时才可用。

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

下面介绍如何安装半同步复制插件
使用半同步复制,需要满足以下条件:
.必须安装MySQL 5.5或更高版本。

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

mysql> show variables like 'have_dynamic_loading';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| have_dynamic_loading | YES   |
+----------------------+-------+
1 row in set (0.01 sec)

.复制必须已经在工作

.不能配置多个复制区域通道。半同步复制只兼容默认复制区域通道。

要设置半同步复制,请使用以下说明。这里提到的INSTALL PLUGIN、SET GLOBAL、STOP SLAVE和START SLAVE语句需要SUPER权限。

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

为了能够被主服务器或从服务器使用,适当的插件库文件必须位于MySQL插件目录中(由plugin_dir系统变量命名的目录)。如果有必要,在服 务器启动时设置plugin_dir的值,告诉服务器插件目录的位置。

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

主插件库文件必须存在于主服务器的插件目录中。从属插件库文件必须存在于每个从属服务器的插件目录中。

要加载插件,请在主服务器和每个半同步的从服务器上使用INSTALL PLUGIN语句(根据需要调整平台的。so后缀)。

主服务器:

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

Query OK, 0 rows affected (0.06 sec)

每个从服务器:

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.03 sec)

如果尝试在Linux上安装插件导致类似于下面所示的错误,你必须安装libimf:

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
ERROR 1126 (HY000): Can't open shared library
'/usr/local/mysql/lib/plugin/semisync_master.so'
(errno: 22 libimf.so: cannot open shared object file:
No such file or directory)

您可以从http://dev.mysql.com/downloads/os-linux.html获取libimf。

要查看安装了哪些插件,请使用SHOW PLUGINS语句,或查询INFORMATION_SCHEMA.PLUGINS表。

要验证插件安装,请检查INFORMATION_SCHEMA。PLUGINS表或使用SHOW PLUGINS语句。

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME          | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE        |
+----------------------+---------------+
1 row in set (0.00 sec)

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
+---------------------+---------------+
| PLUGIN_NAME         | PLUGIN_STATUS |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE        |
+---------------------+---------------+
1 row in set (0.00 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};

主服务器:

mysql> SET GLOBAL rpl_semi_sync_master_enabled =1;
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL rpl_semi_sync_master_timeout =1000;
Query OK, 0 rows affected (0.00 sec)

从服务器:

mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
Query OK, 0 rows affected (0.01 sec)

对于rpl_semi_sync_master_enabled或rpl_semi_sync_slave_enabled,取值为1表示开启半同步复制,取值为0表示关闭半同步复制。默认情况 下,这些变量被设置为0。

对于rpl_semi_sync_master_timeout,值N以毫秒为单位给出。缺省值是10000 (10秒)。

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

mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

mysql> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

主服务器日志:

2024-12-20T08:06:51.512468Z 158 [Note] Stop asynchronous binlog_dump to slave (server_id: 3)
2024-12-20T08:06:51.512514Z 160 [Note] Start binlog_dump to master_thread_id(160) slave_server(3), pos(binlog.000010, 1539)
2024-12-20T08:06:51.512665Z 160 [Note] Start semi-sync binlog_dump to slave (server_id: 3), pos(binlog.000010, 1539)

从服务器日志:

2024-12-16T16:34:53.943377Z 29 [Note] Aborted connection 29 to db: 'jycs' user: 'root' host: 'localhost' (Got timeout reading  communication packets)
2024-12-20T07:57:17.825164Z 37 [Note] Slave I/O thread killed while reading event for channel ''
2024-12-20T07:57:17.825246Z 37 [Note] Slave I/O thread exiting for channel '', read up to log 'binlog.000010', position 1539
2024-12-20T07:57:34.529684Z 40 [Note] Slave I/O thread: Start semi-sync replication to master 'repl@10.138.130.243:3306' in  log 'binlog.000010' at position 1539
2024-12-20T07:57:34.529748Z 40 [Warning] Storing MySQL user name or password information in the master info repository is not  secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see  the 'START SLAVE Syntax' in the MySQL Manual for more information.
2024-12-20T07:57:42.404410Z 40 [Note] Slave I/O thread for channel '': connected to master  'repl@10.138.130.243:3306',replication started in log 'binlog.000010' at position 1539

如果I/O线程已经在运行,而您没有重新启动它,从服务器将继续使用异步复制。
在服务器启动时,可以将控制半同步复制的变量设置为命令行选项或选项文件。选项文件中列出的设置在每次服务器启动时生效。例如,您可以 在主端和从端my.cnf文件中设置如下变量。
主服务器:

[mysql@localhost mysql]$ vi my.cnf
......
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000 # 1 second

从服务器:

[mysql@localhost mysql]$ vi my.cnf
......
[mysqld]
rpl_semi_sync_slave_enabled=1

半同步复制监控
用于半同步复制功能的插件公开了几个系统和状态变量,您可以检查这些变量以确定其配置和操作状态。

系统变量反映了如何配置半同步复制。要查看它们的值,请使用show variables:
主服务器:

mysql> show variables like 'rpl_semi_sync%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 1000       |
| 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 |
+-------------------------------------------+------------+
6 rows in set (0.01 sec)

从服务器:

mysql> show variables like 'rpl_semi_sync%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.01 sec)

通过状态变量,可以监控半同步复制的运行情况。要查看它们的值,使用show status:
主服务器:

mysql> show status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 1     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 1507  |
| Rpl_semi_sync_master_tx_wait_time          | 1507  |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 1     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

从服务器:

mysql> show status like 'rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.01 sec)

当主服务器由于提交阻塞超时或从服务器追赶而在异步或半同步复制之间切换时,它会适当地设置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_tx和Rpl_semi_sync_master_no_tx变量表示从服务器成功或不成功确认的提交数量。

从服务器上的Rpl_semi_sync_slave_status表示半同步复制当前是否处于运行状态。

发表评论

电子邮件地址不会被公开。