续:MySQL的半同步模式

数据库主从复制默认是异步模式。这是MySQL等数据库系统常见的主从复制行为。

异步模式的特点

在异步模式下,主服务器(Master)上的I/O线程将二进制日志(binlog)写入到binlog文件中后,就立即返回客户端结果,而不会等待这些二进制日志是否完整传输到从服务器(Slave)以及是否完整存放到从服务器上的中继日志(relay log)中。这种模式的优点是主服务器能够快速地响应客户端请求,但在主服务器发生故障时,可能会存在数据丢失的风险,因为此时主服务器上已经提交的事务可能还没有被传输到从服务器上。

异步模式的配置步骤

异步模式的配置通常包括以下几个步骤:

  1. 规划server-id:确保主从服务器的server-id唯一。
  2. 安装数据库:根据实际需要选择合适的安装方式安装MySQL数据库。
  3. 修改配置文件:在主从服务器的MySQL配置文件中(通常是my.cnf或my.ini),设置相应的复制参数,如开启binlog、设置server-id等。
  4. 创建复制账号:在主服务器上创建一个用于复制的用户账号,并授权给从服务器。
  5. 备份并还原数据:在主服务器上备份需要复制的数据库,并将备份文件还原到从服务器上。
  6. 配置从服务器:在从服务器上配置主服务器的连接信息,包括主服务器的IP地址、端口号、用户名、密码、binlog文件名和位置等。
  7. 启动复制:在从服务器上启动复制进程,并检查复制状态,确保主从复制正常运行。

半同步模式原理

在异步复制基础上增加了一定程度的同步性,提高数据安全性,减少数据丢失的风险。MySQL半同步模式通过引入等待从服务器确认的机制,有效提高了数据安全性,降低了数据丢失风险,同时保持了相对较低的延迟成本。适用于需要高数据完整性的应用场景。

基本流程

  1. 主服务器(Master)事务处理与binlog记录
    • 客户端向主服务器发起写操作(如INSERT、UPDATE、DELETE等)。
    • 主服务器执行这些操作,并将它们封装在一个或多个事务中。
    • 事务完成后,主服务器将事务的所有更改记录到其本地的二进制日志(Binary Log, binlog)。binlog按顺序记录所有数据修改事件,每个事件包含操作类型、涉及的表名、行数据变化等信息。
  2. binlog事件发送与确认
    • 主服务器上运行一个名为binlog dump线程的后台进程,负责监听从服务器的复制请求。
    • 当从服务器连接到主服务器并请求复制时,binlog dump线程开始读取binlog中的事件,并通过网络将其发送到从服务器。
    • 与异步复制不同之处在于,主服务器在此时会等待至少一个从服务器的确认,即从服务器必须将接收到的binlog事件写入到其本地的中继日志(Relay Log)并反馈给主服务器。
  3. 从服务器处理
    • 从服务器启动一个I/O线程,该线程连接到主服务器并请求从某个特定的binlog位置(如最后一次同步的位置)开始复制。
    • I/O线程接收到主服务器发来的binlog事件后,将其写入到从服务器本地的中继日志。
    • 当I/O线程将binlog事件写入中继日志后,会向主服务器发送一个确认消息(ACK),表明已成功接收并持久化该事件。
  4. 事务完成
    • 当主服务器收到至少一个从服务器的ACK后,它会向客户端确认事务完成,并继续处理后续的事务。

关键改进与优点

  • 数据安全性增强:半同步复制的关键改进在于主服务器在提交事务后,会等待至少一个从服务器确认已接收并持久化该事务的binlog事件。这显著降低了数据丢失的风险,因为在主服务器发生故障时,至少有一个从服务器已经保存了最新的事务数据。
  • 适度延迟:相比异步复制,半同步复制增加了等待从服务器确认的步骤,因此写操作的响应时间会有所增加。但与完全同步复制相比,半同步复制仅需一个从服务器确认即可,延迟相对较小。
  • 回退机制:在网络问题或从服务器延迟过高导致无法及时确认时,为了避免阻塞主服务器,半同步复制可以自动回退到异步模式。一旦条件恢复,可以重新启用半同步复制。

半同步模式示例:

#半同步模式必须设置gtid

#在上一个实验的基础上做半同步模式的MySQL

#在master端配置启用半同步模式

root@mysql1 \~\]# **vim /etc/my.cnf** \[root@mysql1 \~\]# **cat /etc/my.cnf** \[mysqld

datadir=/data/mysql

socket=/data/mysql/mysql.sock

symbolic-links=0

log-bin=mysql-bin

server-id=1

slow_query_log=on

gtid_mode=on

enforce-gtid-consistency=on
rpl_semi_sync_master_enabled=1

#master安装/启用一个插件()

root@mysql1 \~\]# **mysql -uroot -predhat** mysql\> **INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';** Query OK, 0 rows affected (0.02 sec) mysql\> **SHOW DATABASES;** +--------------------+ \| Database \| +--------------------+ \| **information_schema** \| #在这里面 \| folian \| \| mysql \| \| performance_schema \| \| sys \| +--------------------+ 5 rows in set (0.01 sec) mysql\> **SHOW TABLES FROM information_schema;** +---------------------------------------+ \| Tables_in_information_schema \| +---------------------------------------+ ......略 \| **PLUGINS** \| ##我们找的 .....略 mysql\> **SELECT \* FROM information_schema.PLUGINS\\G;** \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 1. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* PLUGIN_NAME: binlog PLUGIN_VERSION: 1.0 ...... \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 39. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* **PLUGIN_NAME: PERFORMANCE_SCHEMA** PLUGIN_VERSION: 0.1 **PLUGIN_STATUS: ACTIVE** PLUGIN_TYPE: STORAGE ENGINE ......略 mysql\> **SELECT \* FROM information_schema.PLUGINS where PLUGIN_NAME LIKE '%SEMI%'\\G;** \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 1. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* **PLUGIN_NAME: rpl_semi_sync_master #我们刚刚安装的已经安装好了** PLUGIN_VERSION: 1.0 PLUGIN_STATUS: ACTIVE .......略 mysql\> **SELECT \* FROM information_schema.PLUGINS where PLUGIN_NAME LIKE '%SEMI%'\\G;** \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 1. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* PLUGIN_NAME: rpl_semi_sync_master PLUGIN_VERSION: 1.0 PLUGIN_STATUS: ACTIVE PLUGIN_TYPE: REPLICATION PLUGIN_TYPE_VERSION: 4.0 PLUGIN_LIBRARY: semisync_master.so PLUGIN_LIBRARY_VERSION: 1.7 PLUGIN_AUTHOR: He Zhenxing PLUGIN_DESCRIPTION: Semi-synchronous replication master PLUGIN_LICENSE: GPL LOAD_OPTION: ON 1 row in set (0.01 sec) ERROR: No query specified #查看 mysql\> **SHOW VARIABLES LIKE 'rpl_semi_sync%';** +-------------------------------------------+------------+ \| Variable_name \| Value \| +-------------------------------------------+------------+ **\| rpl_semi_sync_master_enabled \| ON \|** \| 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 \|** +-------------------------------------------+------------+ 6 rows in set (0.01 sec) mysql\> **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 \| 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) ##严格来讲我们只在主配置文本里写了,但没重启,还需要重启才能打开,或者直接在打开后的MySQL中写SET GLOBAL rpl_semi_sync_master_enabled = 1; 以此来打开半同步功能。 # # #在slave端开启半同步功能 slave1 slave2 \[root@mysql2 \~\]# vim /etc/my.cnf \[root@mysql2 \~\]# cat /etc/my.cnf \[mysqld

datadir=/data/mysql

socket=/data/mysql/mysql.sock

symbolic-links=0

server-id=2

gtid_mode=on

enforce-gtid-consistency=on
rpl_semi_sync_slave_enabled=1

root@mysql2 \~\]#**/etc/init.d/mysqld start** Starting MySQL.... SUCCESS! \[root@mysql2 \~\]# **mysql -uroot -predhat** mysql\> **INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';** Query OK, 0 rows affected (0.03 sec) mysql\> **SET GLOBAL rpl_semi_sync_slave_enabled =1;** Query OK, 0 rows affected (0.00 sec) 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) 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) mysql\> SHOW STATUS LIKE 'Rpl_semi_sync%'; +----------------------------+-------+ \| Variable_name \| Value \| +----------------------------+-------+ \| Rpl_semi_sync_slave_status \| ON \| +----------------------------+-------+ 1 row in set (0.01 sec) slave2(mysql3同上) #**测试** 在 master 端写入数据 mysql\> insert into folian.userlist values ('user2','123'); Query OK, 1 row affected (0.03 sec) mysql\> show status like 'Rpl_semi_sync%'; +--------------------------------------------+-------+ \| Variable_name \| Value \| +--------------------------------------------+-------+ \| Rpl_semi_sync_master_clients \| 2 \| \| 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 \| 1464 \| \| Rpl_semi_sync_master_tx_wait_time \| 1464 \| \| 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) 故障模拟:在两个slave端 mysql\> STOP SLAVE IO_THREAD; Query OK, 0 rows affected (0.00 sec) #又在master端插入数据 mysql\> insert into folian.userlist values ('user3','555'); Query OK, 1 row affected (10.01 sec) mysql\> show status like 'Rpl_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 \| 1464 \| \| Rpl_semi_sync_master_tx_wait_time \| 1464 \| \| 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.01 sec)

相关推荐
鬼才血脉16 分钟前
Linux(centos)安装 MySQL 8
linux·mysql·centos
float_六七2 小时前
SQL六大核心类别全解析
数据库·sql·oracle
Code季风3 小时前
将 gRPC 服务注册到 Consul:从配置到服务发现的完整实践(上)
数据库·微服务·go·json·服务发现·consul
Boilermaker19923 小时前
【Java EE】SpringIoC
前端·数据库·spring
霸王龙的小胳膊4 小时前
泛微虚拟视图-数据虚拟化集成
数据库
灵犀学长4 小时前
解锁Spring Boot多项目共享Redis:优雅Key命名结构指南
数据库·redis
轩情吖4 小时前
Qt的信号与槽(二)
数据库·c++·qt·信号·connect·信号槽·
ZeroNews内网穿透4 小时前
服装零售企业跨区域运营难题破解方案
java·大数据·运维·服务器·数据库·tcp/ip·零售
可观测性用观测云4 小时前
达梦数据库监控观测最佳实践
数据库
时序数据说4 小时前
IoTDB:专为物联网场景设计的高性能时序数据库
大数据·数据库·物联网·开源·时序数据库·iotdb