MySQL 复制-半同步搭建及原理
前言
MySQL 半同步复制解决了什么问题?
在传统主从架构中,主库实例提交事务与发送二进制日志是异步的,也就是说从库是否成功接收到二进制日志不会影响到主库事务提交,因此可能会出现 “主库发生宕机,主库已提交事务的二进制日志并没有被任何从库成功接收的情况”
造成数据丢失。为了避免此类情况发生,MySQL 对传统复制进行改进,引入半同步复制。
一、半同步复制搭建操作过程
1. 部署传统异步复制
异步复制部署可参考,云掣官网:
《MySQL 复制-无数据环境搭建异步复制》
《MySQL 复制-有数据环境搭建异步复制》
2. 半同步复制插件安装与配置
如果你已经有了异步复制的环境,接下来就可以进行半同步复制插件安装和配置,因为半同步复制并非 MySQL 内置,而是需要单独安装对应的插件才能启用,安装完成也可以系统变量来控制半同步是否启动或禁用。下面详细介绍操作过程。
2.1. 确认环境是否可用
确认 MySQL Server 是否支持在线安装插件,可以使用下方 SQL 来确认:
-- 查询是否支持动态加载插件 show variables like 'have_dynamic_loading';
2.2. 安装半同步插件
安装前可以先确认一下目前环境是否已经安装过半同步插件:
-- 查询目前已安装的插件 show plugins;
安装半同步插件(主库)
-- 安装半同步插件-主库 INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
安装半同步插件(从库)
-- 安装半同步插件-从库 INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
主从查询半同步插件是否可用:
-- 从元数据中查询半同步复制插件状态 select PLUGIN_NAME,PLUGIN_VERSION,PLUGIN_STATUS from information_schema.plugins where PLUGIN_NAME like '%semi%';
2.3. 配置启动半同步插件
半同步插件安装后,默认是关闭的需要我们手动启动一下~
-- 启动半同步复制-主库 set global rpl_semi_sync_master_enabled=1; -- 启动半同步复制-从库 set global rpl_semi_sync_slave_enabled=1;
检查半同步复制是否启动,主从都需要检查:
show status like '%semi%status%';
此时我们发现从库设置 rpl_semi_sync_slave_enabled 以后半同步复制的状态依然是 OFF 那是因为异步复制正在运行,我们需要重启从库的 IO 线程后才会生效。
stop slave io_thread; start slave io_thread;
2.4. 参数持久化
将半同步配置写入到配置文件中,配置文件中的选项在 MySQL Server 启动时都会生效。
-- 主库 rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout = 10000
-- 每个从库 rpl_semi_sync_slave_enabled=1
3. 半同步复制工作状态验证
3.1. 主库制造测试数据
create database rep_test; use rep_test; create table rep_test_table2(id int); insert into rep_test_table2 values(1),(2),(3);
3.2. 主库查看半同步复制的状态
root@mysql 14:37: [(none)]>show status like '%semi%tx%'; +---------------------------------------+-------+ | Variable_name | Value | +---------------------------------------+-------+ | Rpl_semi_sync_master_no_tx | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 7693 | | Rpl_semi_sync_master_tx_wait_time | 76933 | | Rpl_semi_sync_master_tx_waits | 10 | | Rpl_semi_sync_master_yes_tx | 10 | +---------------------------------------+-------+ 5 rows in set (0.01 sec)
查询出来的都是关于半同步复制的状态值,下面介绍具体含义:
Rpl_semi_sync_master_no_tx:是 MySQL 状态变量,表示使用异步复制给从发送事务日志的次数,也就是说如果该值不停的增长,则表示复制已经降级为异步复制。
看过一些文章讲 Rpl_semi_sync_master_no_tx
参数不等于 0 就表示使用传统异步方式去复制,其实不然,它表示的是使用异步复制给从库发送日志的次数,只要不增长就表示目前使用的就是半同步复制。我们使用在线配置半同步复制的方式,生效是需要一些时间的,所以在半同步生效之前,可能也会有些事务通过异步复制的方式到从库,属于正常情况,只有该值不会持续增加就表示正常,所以配置完成做一个测试很重要哦~ 如果发现该值持续增加,那就需要立即检查配置是否正常,或者主从之间网络中断导致半同步复制降级为异步复制。
当然也可以通过下方 SQL 拿到更详细的半同步状态信息:
SHOW STATUS LIKE 'Rpl_semi_sync%';
Rpl_semi_sync_master_status
为 ON 则表示使用半同步复制正常,为 OFF 则表示已降级为异步复制 更详细请参考 MySQL 官方文档-半同步复制监控
二、半同步复制原理
1. 传统复制的缺陷
主库通过二进制日志实现与从库的数据同步,由于异步复制发送二进制日志与从库接收是异步的,也就是说主库发送二进制日志后,从库有没有接收到是不会影响主库的事务提交的,在故障切换过程中,很可能出现数据丢失的情况。
2. 半同步复制原理
异步复制对与主从数据的一致性没有太好的保障,MySQL 对异步复制进行改进,引入半同步复制。下图是 MySQL 官方描述半同步复制时间线,我们发现在 binlog 阶段后 commit 阶段前,主库需要等待从库在 relay log 阶段完成后回复 ACK 消息。从库在回复 ACK 消息前,确保已经接收 binlog 日志并且已写入中继日志,这样就算主库如果发生宕机,可以保障已提交的事务都已经写入从库中继日志,避免发送故障时出现数据丢失。
2. 异步复制与半同步复制对比
使用传统异步复制,主库将事件写入到二进制日志,从库请求这些日志,并将其写入到自己的中继日志,整个过程无法保障所有的事件都能被从库接收并写入到中继日志。
使用半同步复制,主库在提交事务时,必须等待日志成功在从库写入,主从数据的一致性得到保障,但是也会造成主库事务延迟提交,有时你会看到主库的事件状态为 Waiting for semi-sync ACK from slave
等待从库的 ACK 消息。
对数据一致性有要求的场景,可以使用半同步复制代替异步复制,如果对数据一致性要求不高,对数据同步效率要求较高,传统异步复制就可以满足。
3. 半同步中的 “半” 指的什么?
主库不需要等待从库完成事件重放,主库等待至少一个从库的 ACK 消息即可,就是说只需要等待从库成功接收即可,不需要等待从库事务提交。
三、半同步参数变量相关
1. 相关参数
rpl_semi_sync_master_timeout
一个以毫秒为单位的值,用于控制主库超时并切换为异步复制之前,等待从库返回 ACK 消息的时间,默认值为 10000 (10 秒)。
rpl_semi_sync_master_wait_for_slave_count
主库需要等待多少个从库发送的 ACK 信息后,执行存储引擎层事务提交,默认为 1 台。
rpl_semi_sync_master_wait_point
控制半同步复制中主库返回事务提交状态信息给提交事务的客户端之前,等待从库 ACK 消息的点位。有效值有两个:AFTER_SYNC
& AFTER_COMMIT
。
AFTER_SYNC:主库在未收到从库的 ACK 消息之前,发起事务提交的会话不会收到事务提交结果,存储引擎层也不会执行提交。当主库收到 ACK 消息之后,主库在存储引擎层执行事务提交,再将事务提交结果返回给提交事务的客户端。整个过程所有的客户端看到的数据都相同,如果主库发生故障,则在主库上提交的所有事务至少已经存储在一个从库中,主库发生故障后数据是无损的。
AFTER_COMMIT:主库在未收到从库的 ACK 消息之前,发起事务提交的会话不会收到事务提交结果,但存储引擎层会先执行提交。所以在事务提交之后,未收到 ACK 消息之前,主库的其它客户端是可以看到这个事务的,对其它会话来说,这个事务已经完成提交了。如果在这种情况下发送故障,主库已提交的事务(可能是最后一个事务)二进制日志还没来得及被从库成功接收,那么主库发生故障转移后,原来能在主库上查询到的事务,在业务切换到从库之后在从库中无法查询到,发生数据丢失。
2. 状态变量
可以通过 show status 查看关于半同步的状态变量,可以监控半同步复制的状态。
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_slve_status
从库端,半同步复制插件当前的可用状态。
3. 半同步复制监控
-- 通过系统变量查询半同步复制是否配置正确 show variables like '%Rpl_semi_sync%'; -- 通过查询状态变量查询半同步复制的工作状态 show status like '%Rpl_semi_sync%';