MySQL 半自动复制
官网:https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html
简介
- 半同步复制,它向协议添加了一个同步步骤。这意味着主服务器在提交时等待辅助服务器确认已接收到该事务。只有这样,主服务器才会恢复提交操作。而这有两种等待应答的机制。
应答等待机制
-
两者主要的区别: 提交到存储引擎时间,AFTER_SYNC 在收到副本的收到确认请求之后,再提交到存储引擎,AFTER_COMMIT 则是在源操作完,就提交到存储引擎,不关心副本是否收到。
-
AFTER_SYNC(默认) :源将每个事务写入其二进制日志和副本,并将二进制日志同步到磁盘。同步后,源将等待事务接收的副本确认。收到确认后,源将事务提交到存储引擎,并将结果返回给客户端,然后客户端可以继续进行。
-
AFTER_COMMIT:源将每个事务写入其二进制日志和副本中,同步二进制日志,然后将事务提交到存储引擎。提交后,源将等待事务回执的副本确认。收到确认后,源将结果返回给客户端,然后客户端可以继续进行。
额外注意点
- 当应答等待无响应时,有两种处理方法,
- 一 、死等,只到有应答为止。
- 二、从半同步退化到异步,如此的风险是,副本上可能没有数据,造成数据缺失。
- 金融行业,等待超时时间设置为无穷大,必须同步,无损。
- mysql 超百万查询速率下降。
解决方法:分库,分表
异步缺陷
- 默认情况下,MySQL复制是异步的。源将事件写入其二进制日志,副本将在事件就绪时请求它们。源不知道副本是否或何时检索和处理了事务,并且不能保证任何事件都会到达副本。使用异步复制,如果源崩溃,则它提交的事务可能不会传输到任何副本。在这种情况下,从源到副本的故障转移可能会导致故障转移到缺少相对于源的事务的服务器。
半同步优势
- 半同步复制介于异步复制和完全同步复制之间。源等待直到至少一个副本接收并记录了事件(所需数量的副本是可配置的),然后提交事务。源不等待所有副本都确认接收,它仅需要副本的确认,而不是事件已在副本端完全执行并提交。因此,半同步复制可确保如果源崩溃,则它已提交的所有事务都已传输到至少一个副本。
半同步复制管理接口
半同步复制的管理接口包含几个组件:
-
两个插件实现了半同步功能。源端有一个插件,副本端有一个插件。
-
系统变量控制插件的行为。一些例子:
-
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,但控制副本插件。
-
实验
主机 | IP |
---|---|
server1 ( master ) | 172.25.9.1 |
server2 ( master, slave ) | 172.25.9.2 |
serve3 (slave) | 172.25.9.3 |
- 基于主从的线性复制:server1 (master) -> server2 (master,slave) -> server3 (slave)
# server1:
# 安装master 端的插件,并启动
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled =1;
# server2:
# 安装master 端和 slave 端的插件,并启动,因为是基于线性的,server2 既是master 也是 slave
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_master_enabled =1;
SET GLOBAL rpl_semi_sync_slave_enabled =1;
# server3:
# 安装slave 端的插件,并启动
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled =1;
# server1,server2,server3:
# 启动插件需要重启 I/O 线程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
# 查询相应的插件是否启动
show variables like 'rpl%';
show status like 'rpl%';
示例截图: