1.主从复制原理
在MySQL主从复制中,大体上有三个线程,master端有一个dump 线程,slave端有两个线程,i/o 线程和sql线程。
当有数据写入后,master 端的dump线程将bin log发送到slave端的io线程,i/o线程接收后,将其存放在本地的relay log中。
sql线程读取relay log,接着重放 event,更新数据。
主从复制有三种方式:
- 异步复制
- 同步复制
- 半同步复制
其中,同步复制中,master执行一个事务后,要求所有的slave都执行完成后,才会返回给客户端。这样,在性能上,是有影响的。同步复制的优势,就是不丢失数据。缺点,就是复制效率低。
MySQL自身不支持同步复制,需要用第三方工具如DRBD(sync模式)等实现同步复制。
异步复制中,master 更新操作写入binlog后,就会返回给客户端。不关心,slave 是否接收到binlog,以及是否应用了更新。异步复制的优势,是复制效率高。缺点是,可能会丢失数据。
半同步复制(semi-sync repication),是介于同步复制和异步复制之间的一种复制方式。主库在执行完客户端提交的事务之后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端(极端情况下,如果等待超时,会退化为异步复制)。相对于异步复制,半同步复制提高了数据的安全性。
2.半同步复制环境搭建
下文使用的是单机多实例环境,具体搭建过程可参考单机安装MySQL多实例。
MySQL版本是 5.7.27。
MySQL主从集群信息如下:
角色 | ip | port |
---|---|---|
主库 | 127.0.0.1 | 3306 |
从库 | 127.0.0.1 | 3307 |
2.1 半同步插件安装和配置
MySQL安装包中,已经自带MySQL半同步插件。
$ ll /application/mysql/lib/plugin/semi*
-rwxr-xr-x. 1 lanyang lanyang 708586 Jun 10 2019 /application/mysql/lib/plugin/semisync_master.so
-rwxr-xr-x. 1 lanyang lanyang 152341 Jun 10 2019 /application/mysql/lib/plugin/semisync_slave.so
2.1.1 主库半同步插件安装和配置
安装插件
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)
mysql>
主库开启半同步
mysql> set global rpl_semi_sync_master_enabled = 1;
Query OK, 0 rows affected (0.01 sec)
mysql>
配置半同步超时参数(单位ms)
mysql> set global rpl_semi_sync_master_timeout = 1000;
Query OK, 0 rows affected (0.00 sec)
mysql>
该参数表示主库等待从库ack的时间,如果超时,半同步复制就退化为异步复制。
此处配置的超时时间是1s。
在配置文件添加,使其永久生效:
[mysqld]
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 1000
查看半同步插件安装和配置状态
mysql> select * from mysql.plugin;
+----------------------+--------------------+
| name | dl |
+----------------------+--------------------+
| rpl_semi_sync_master | semisync_master.so |
+----------------------+--------------------+
1 row in set (0.00 sec)
主库半同步复制的状态参数
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| 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 | ON |
| 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.00 sec)
其中,Rpl_semi_sync_master_clients
有多少个开启了半同步复制的从库。
Rpl_semi_sync_master_net_avg_wait_time
master等待slave回复的平均网络等待时间。
Rpl_semi_sync_master_net_wait_time
总网络等待时间。
Rpl_semi_sync_master_net_waits
master等待slave回复总的网络等待次数。
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_yes_tx
接收确认次数。
Rpl_semi_sync_master_no_times
关闭半同步复制的次数。
Rpl_semi_sync_master_no_tx
查看有多少事务没有使用半同步复制的机制进行复制,也就是master等待超时的次数。
主库半同步复制的相关参数配置
mysql> show global variables like '%semi%';
+-------------------------------------------+------------+
| 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.00 sec)
其中,
rpl_semi_sync_master_wait_for_slave_count
表示主库事务提交前,在指定的时间rpl_semi_sync_master_timeout
超时之前,必须有这个指定数量的从库确认已接收到。
如果超时之前,仍然没有得到rpl_semi_sync_master_wait_for_slave_count
这个数量的从库确认,则退化为异步复制。
默认值1,即超时之前,需要有一个从库确认已接收到bin log,事务才可以提交。
对于
rpl_semi_sync_master_wait_no_slave
,表示是否每个事务提交后都需要等待从库的接收确认信号。
如果为ON
(默认是ON
),只要指定数量的从库在超时之前确认已接收,则半同步复制会继续。
如果为OFF
,表示在超时之前,没有达到指定数量从库已确认接收。则退化为异步复制。
2.1.2 从库半同步插件安装和配置
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.02 sec)
mysql>
从库开启半同步
mysql> set global rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
mysql>
添加到配置文件使其永久生效:
[mysqld]
rpl_semi_sync_slave_enabled = 1
配置后,记得重启下i/o线程。
查看从库上半同步复制状态和参数:
mysql> show global status like '%semi%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.00 sec)
mysql> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
2 rows in set (0.00 sec)
接着,查看主库上的半同步复制状态:
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
+--------------------------------------------+-------+
... ...
14 rows in set (0.00 sec)
显示已有一个从库通过半同步复制连接到主库。
2.2 半同步复制测试
2.2.1 测试1--简单测试
在主库上写入两条数据:
mysql> insert into app.test(service_group_name) values('abc001');
Query OK, 1 row affected (0.01 sec)
mysql> insert into app.test(service_group_name) values('abc002');
Query OK, 1 row affected (0.00 sec)
查看主库上的半同步复制状态:
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| 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 | 2 |
| 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 | 472 |
| Rpl_semi_sync_master_tx_wait_time | 472 |
| 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 | 2 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
mysql>
2.2.2 测试2--超时测试
(1)停止从库的i/o线程
停止从库的i/o线程,可以使半同步复制超时。
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec)
(2)在主库上写入数据
mysql> insert into app.test(service_group_name) values('abc003');
Query OK, 1 row affected (1.01 sec)
mysql>
可以看到执行时间1.01s。
查看此时的半同步复制状态:
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| 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 | 2 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 472 |
| Rpl_semi_sync_master_tx_wait_time | 472 |
| 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 | 2 |
+--------------------------------------------+-------+
14 rows in set (0.01 sec)
Rpl_semi_sync_master_no_times
关闭半同步的次数为1。
Rpl_semi_sync_master_no_tx
等待超时的次数,为1.
Rpl_semi_sync_master_status
半同步状态处于关闭状态。
(3)从库开启i/o 线程
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
(4)再次查看主库上半同步复制状态
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| 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 | 3 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 472 |
| Rpl_semi_sync_master_tx_wait_time | 472 |
| 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 | 2 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
从库复制后,主库半同步复制状态又变为ON。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2018-10-07 npm是什么
2018-10-07 菜鸟如何学习vue