续: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)

相关推荐
瀚高PG实验室9 小时前
业务无法通过hgproxy访问数据库
数据库·postgresql·瀚高数据库
鱼很腾apoc10 小时前
【MySQL】 第1期 从核心概念到表约束全解析
linux·c语言·数据库·学习·mysql
10mAh10 小时前
【SQL】NOT IN 遇到 NULL 为什么返回空集?三值逻辑与反关联实战
jvm·数据库·sql
Alinket10 小时前
毫米波雷达 vs 摄像头 vs 手环:养老跌倒监测三类方案怎么选
网络·数据库·健康医疗·信息与通信·iot
七夜zippoe10 小时前
Agent 权限边界:别让 AI 误删你的生产库(安全设计)
数据库·人工智能·安全·ai·权限边界·安全设计
泡海椒10 小时前
JQuickExcel 批量导入:用 importDataInBatch 控制大文件消费边界
数据库·oracle
码流子10 小时前
事件告警延迟拆解:从摄像头到手机通知,延迟卡在哪六个环节
数据库·人工智能·物联网
斯内普吖11 小时前
(开源)校园充电宝租借管理系统实战指南 基于 Java + SSM + Vue + MySQL
java·vue.js·mysql·开源
啵啵啵鱼11 小时前
对数据的增删改查
数据库·mysql·ai·idea·ai编程·navicat·obsidian
靠沿11 小时前
MySQL数据库基础——索引的使用&alter、explain关键字
java·数据库·mysql