半同步复制(Semi-synchronous Replication)

MySQL5.5之前,MySQL的复制是异步操作,主库和从库的数据之间存在一定的延迟。这样存在一定的隐患:当主库上写入一个事务并

交成功,而从库尚未得到主库推送的Binlog日志时,主库宕机了,例如主库可能因磁盘损坏、内存故障等造成主库上该事务Binlog丢失,此时从库就可能损失这个事务,从而造成主从不一致。

为了解决这个问题,MySQL5.5引入了半同步复制机制。在MySQL5.5之前的异步复制时,主库完成了Commit提交操作之后,在主库写

Binlog日志后即可成功返回客户端,无需等待Binlog日志传送给从库。

而半同步复制时,为了保证主库上的每一个Binlog事务都能够被可靠的复制到从库上,主库在每次事务提交时,并不及时反馈给前

台应用用户,而是等待其中一个从库也接收到Binlog事务并成功写入中继日志后,主库才返回Commit操作成功给客户端。半同步复制保证

了事务成功提交后,至少有两份日志记录,一份在主库的Binlog日志上,另一份在至少一台从库的中继日志Relay Log上,从而更进一步

保证了数据的完整性。

半同步复制模式下,如果主库在事务提交前的任何一个环节故障,则事务提交不成功,从库上也没收到事务对应的Binlog日志,所

以主从数据是一致的;假如在主库传送Binlog日志到从库过程中,从库宕机或网络故障,导致Binlog并没有及时地传送到从库上,此时

主库的事务会等待一段时间(时间长短由rpl_semi_sync_master_timeout设置的秒数决定),如果Binlog在这段时间内无法成功推送到从

库上,则MySQL自动调整复制为异步模式,事务正常返回提交结果给客户端

半同步很大程度上取决于主从库之间的网络状况,往返时延RTT越小决定了从库实时性越好。通俗的说主从之间的网络越快从库越实

时。

半同步模式是作为MySQL5.5的一个插件来实现的,主库和重开使用不同的插件,安装比较简单,在上一节异步复制的基础上,安装

半同步复制插件即可。

(1)、首先,判断MySQL服务器是否支持动态增加插件:

MariaDB [(none)]> select @@have_dynamic_loading;

+------------------------+

| @@have_dynamic_loading |

+------------------------+

| YES                    |

+------------------------+

1 row in set (0.01 sec)

(2)、确认支持增加插件后,检查MySQL的安装目录下是否存在插件,一般默认在$MYSQL_HOME/lib/plugin目录下存在主库插件

semisync_master.so和从库插件semisync_slave.so

[[email protected] ~]# ls /usr/local/mysql/lib/plugin/semisync_*

-rwxr-xr-x 1 root root 510355 Jun 13 09:44 /usr/local/mysql/lib/plugin/semisync_master.so

-rwxr-xr-x 1 root root 427031 Jun 13 09:45 /usr/local/mysql/lib/plugin/semisync_slave.so

在主库上安装插件semisync_master.so:

MariaDB [(none)]> install plugin rpl_semi_sync_master soname ‘semisync_master.so‘;

Query OK, 0 rows affected (0.07 sec)

从库上则安装semisync_slave.so:

MariaDB [(none)]> install plugin rpl_semi_sync_slave soname ‘semisync_slave.so‘;

Query OK, 0 rows affected (0.08 sec)

安装完成后,从plugin表中看到刚才安装的插件:

MariaDB [(none)]> select * from mysql.plugin;

+----------------------+--------------------+

| name                 | dl                 |

+----------------------+--------------------+

| rpl_semi_sync_master | semisync_master.so |

+----------------------+--------------------+

1 row in set (0.00 sec)

MariaDB [(none)]> select * from mysql.plugin;

+---------------------+-------------------+

| name                | dl                |

+---------------------+-------------------+

| rpl_semi_sync_slave | semisync_slave.so |

+---------------------+-------------------+

1 row in set (0.00 sec)

也就是说,安装完成后,MySQL会在系统表plugin中记录刚才安装的插件,下次重启后会自动加载插件。

(3)、需要分别在主库和从库上配置参数打开半同步 semi-sync,默认半同步设置是不打开的,

主库上配置全局参数:

MariaDB [(none)]> set global rpl_semi_sync_master_enabled=1;

Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> set global rpl_semi_sync_master_timeout=30000;

Query OK, 0 rows affected (0.00 sec)

MariaDB [pancou]> show variables like ‘%rpl_semi%‘;

+------------------------------------+-------+

| Variable_name                      | Value |

+------------------------------------+-------+

| rpl_semi_sync_master_enabled       | ON    |

| rpl_semi_sync_master_timeout       | 30000 |

| rpl_semi_sync_master_trace_level   | 32    |

| rpl_semi_sync_master_wait_no_slave | ON    |

+------------------------------------+-------+

4 rows in set (0.00 sec)

从库上一样的配置参数:

MariaDB [(none)]> set global rpl_semi_sync_slave_enabled=1;

Query OK, 0 rows affected (0.00 sec)

MariaDB [pancou]> 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.00 sec)

注意,由于之前配置的复制是异步复制,所以要重启一下从库上的I/O线程(如果是全新配置的半同步复制则不需要):

MariaDB [(none)]> stop slave io_thread;start slave io_thread;

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

至此半同步配置完毕,下面可以来验证一下。主库上通过show status命令能够看到当前半同步复制的一些状态值:

MariaDB [(none)]> show status like ‘%semi_sync%‘;

+--------------------------------------------+-------+

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

着重关注以下3个状态值:

Rpl_semi_sync_master_status:值为ON,表示半同步复制目前处于打开状态。

Rpl_semi_sync_master_yes_tx:值为0,表示主库当前尚未有任何一个事务时通过半同步复制到从库。

Rpl_semi_sync_master_no_tx: 值为0,表示当前有0个事务不是通过半同步模式下从库及时响应的(记住只给值,后面有对比)。

执行一个事务,再检查一下:

MariaDB [pancou]> create table emp(emp_id smallint,emp_name varchar(10));

Query OK, 0 rows affected (0.10 sec)

MariaDB [pancou]> insert into emp values(1,‘tom‘),(2,‘jerry‘);

Query OK, 2 rows affected (0.01 sec)

Records: 2  Duplicates: 0  Warnings: 0

MariaDB [pancou]> show status like ‘%semi_sync%‘;

+--------------------------------------------+-------+

| Variable_name                              | Value |

+--------------------------------------------+-------+

| Rpl_semi_sync_master_clients               | 1     |

| Rpl_semi_sync_master_net_avg_wait_time     | 1496  |

| Rpl_semi_sync_master_net_wait_time         | 2992  |

| 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      | 1203  |

| Rpl_semi_sync_master_tx_wait_time          | 2407  |

| Rpl_semi_sync_master_tx_waits              | 2     |

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

此时会发现Rpl_semi_sync_master_yes_tx值变为2,即刚才的create 和 insert事务通过半同步复制到从库上了,

Rpl_semi_sync_master_yes_tx 基数增加到2,到从库上确认一下:

MariaDB [pancou]> select * from emp;

+--------+----------+

| emp_id | emp_name |

+--------+----------+

|      1 | tom      |

|      2 | jerry    |

+--------+----------+

2 rows in set (0.00 sec)

再尝试一下网络异常的场景下,主库等待rpl_semi_sync_master_timeout毫秒超时后,自动转成异步复制的场景。

(1)、首先,在主库上确认半同步会等待30秒超时;

MariaDB [pancou]> show variables like ‘%semi%time%‘;

+------------------------------+-------+

| Variable_name                | Value |

+------------------------------+-------+

| rpl_semi_sync_master_timeout | 30000 |

+------------------------------+-------+

1 row in set (0.00 sec)

(2)、在主库上通过iptables命令模拟从库宕机或网络故障:

第二天

MariaDB [pancou]> set global rpl_semi_sync_master_enabled=1;

Query OK, 0 rows affected (0.00 sec)

show variables like ‘rpl_semi_%‘;

+------------------------------------+-------+

| 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_no_slave | ON    |

+------------------------------------+-------+

4 rows in set (0.01 sec)

MariaDB [pancou]> show status like ‘%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)

MariaDB [pancou]> delete from emp where emp_id=2;

Query OK, 1 row affected (0.01 sec)

MariaDB [pancou]> show status like ‘%semi_sync%‘;

+--------------------------------------------+-------+

| Variable_name                              | Value |

+--------------------------------------------+-------+

| Rpl_semi_sync_master_clients               | 1     |

| Rpl_semi_sync_master_net_avg_wait_time     | 1494  |

| Rpl_semi_sync_master_net_wait_time         | 1494  |

| Rpl_semi_sync_master_net_waits             | 1     |

| 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                | 1     |

+--------------------------------------------+-------+

14 rows in set (0.00 sec)

在从库上

iptables -I INPUT -s 192.168.110.128 -j DROP

(3)、在主库上执行一个事务并提交(默认提交即可),主库上的提交操作会被阻塞30秒:

MariaDB [pancou]> insert into emp values(2,‘jerry‘);

---等待

新打开一个主库的线程

MariaDB [(none)]> show processlist\G

*************************** 1. row ***************************

Id: 7

User: root

Host: localhost

db: NULL

Command: Query

Time: 0

State: init

Info: show processlist

Progress: 0.000

*************************** 2. row ***************************

Id: 10

User: root

Host: localhost

db: pancou

Command: Query

Time: 4

State: Waiting for semi-sync ACK from slave

Info: insert into emp values(2,‘jerry‘)

Progress: 0.000

*************************** 3. row ***************************

Id: 11

User: repl_user

Host: 192.168.110.130:52165

db: NULL

Command: Binlog Dump

Time: 2037

State: Reading from net

Info: NULL

Progress: 0.000

3 rows in set (0.00 sec)

MariaDB [(none)]> show processlist\G

*************************** 1. row ***************************

Id: 6

User: root

Host: localhost

db: pancou

Command: Sleep

Time: 248

State:

Info: NULL

Progress: 0.000

*************************** 2. row ***************************

Id: 7

User: root

Host: localhost

db: NULL

Command: Query

Time: 0

State: init

Info: show processlist

Progress: 0.000

2 rows in set (0.00 sec)

(4)、主库上等待30秒后

Query OK, 1 row affected (10.00 sec)

MariaDB [pancou]> insert into emp values(2,‘jerry‘);

Query OK, 1 row affected (0.01 sec)

检查半同步的状态值

MariaDB [pancou]> show status like ‘%semi_sync%‘;

+--------------------------------------------+----------+

| Variable_name                              | Value    |

+--------------------------------------------+----------+

| Rpl_semi_sync_master_clients               | 0        |

| Rpl_semi_sync_master_net_avg_wait_time     | 15016390 |

| Rpl_semi_sync_master_net_wait_time         | 30032780 |

| Rpl_semi_sync_master_net_waits             | 2        |

| Rpl_semi_sync_master_no_times              | 1        |

| Rpl_semi_sync_master_no_tx                 | 2        |

| Rpl_semi_sync_master_status                | OFF      |

| 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                | 1        |

+--------------------------------------------+----------+

14 rows in set (0.00 sec)

Rpl_semi_sync_master_status                | OFF

Rpl_semi_sync_master_yes_tx                | 1   刚才并没有通过半同步复制完成,所以半同步并没有累加

Rpl_semi_sync_master_no_tx                 | 2

继续之前的场景下从库正常连接上主机之后,确认是否会自动切换回半同步复制模式。

iptables -D INPUT 1

检查从库上的状态:

MariaDB [pancou]> show slave status\G

*************************** 1. row ***************************

Slave_IO_State: Waiting for master to send event

Master_Host: 192.168.110.128

Master_User: repl_user

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: mysql-bin.000005

Read_Master_Log_Pos: 1940

Relay_Log_File: www-relay-bin.000011

Relay_Log_Pos: 1024

Relay_Master_Log_File: mysql-bin.000005

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

Replicate_Do_DB:

Replicate_Ignore_DB:

(2)、检查半同步复制状态值

MariaDB [pancou]> show status like ‘%semi_sync%‘;

+--------------------------------------------+----------+

| Variable_name                              | Value    |

+--------------------------------------------+----------+

| Rpl_semi_sync_master_clients               | 1        |

| Rpl_semi_sync_master_net_avg_wait_time     | 10019692 |

| Rpl_semi_sync_master_net_wait_time         | 30059077 |

| Rpl_semi_sync_master_net_waits             | 3        |

| Rpl_semi_sync_master_no_times              | 1        |

| Rpl_semi_sync_master_no_tx                 | 3        |

| 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                | 1        |

+--------------------------------------------+----------+

14 rows in set (0.00 sec)

Rpl_semi_sync_master_status            值自动由OFF变为 | ON ,说明主库检测到正常以后主库到从库的复制方式自动切换为

半同步方式

(3)、在主库上做一个测试

MariaDB [pancou]> insert into emp values(3,‘bob‘);

Query OK, 1 row affected (0.01 sec)

MariaDB [pancou]> show status like ‘%semi_sync%‘;

+--------------------------------------------+----------+

| Variable_name                              | Value    |

+--------------------------------------------+----------+

| Rpl_semi_sync_master_clients               | 1        |

| Rpl_semi_sync_master_net_avg_wait_time     | 7515331  |

| Rpl_semi_sync_master_net_wait_time         | 30061326 |

| Rpl_semi_sync_master_net_waits             | 4        |

| Rpl_semi_sync_master_no_times              | 1        |

| Rpl_semi_sync_master_no_tx                 | 3        |

| Rpl_semi_sync_master_status                | ON       |

| Rpl_semi_sync_master_timefunc_failures     | 0        |

| Rpl_semi_sync_master_tx_avg_wait_time      | 742      |

| Rpl_semi_sync_master_tx_wait_time          | 742      |

| 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_yes_tx         由1变为 2,确认刚才事务是半同步复制。

从半同步复制的流程会发现,半同步复制的 “半” 就体现在:虽然主库和从库的Binlog日志是同步的,但是主库并不等待从库应用这部分

日志就返回提交结果,这部分操作是异步的,从库的数据并不是和主库实时同步的,所以只能称之为半同步而不是完全的实时同步。

时间: 2024-09-30 16:23:04

半同步复制(Semi-synchronous Replication)的相关文章

Mysql5.7基于GTID的半同步复制

一.GTID是什么 GTID是事务的ID,唯一识别号,全局唯一.随事务记录到Binary Log中,用来标识事务.每个事务有一个Gtid_log_event.GTID的构成:UUID + Sequence Number Sequence Number是MySQL服务器内部的一个事务顺序号.一个MySQL服务器上的事务不会有重复的顺序号(保证服务器内唯一).每个MySQL服务器有一个全局唯一的UUID. GTID的目的简化复制的使用过程和降低复制集群维护的难度,不再依赖Master的binlog文

Mysql半同步复制模式说明 - 运维小结

MySQL主从复制包括异步模式.半同步模式.GTID模式以及多源复制模式,默认是异步模式 (如之前详细介绍的mysql主从复制).所谓异步模式指的是MySQL 主服务器上I/O thread 线程将二进制日志写入binlog文件之后就返回客户端结果,不会考虑二进制日志是否完整传输到从服务器以及是否完整存放到从服务器上的relay日志中,这种模式一旦主服务(器)宕机,数据就可能会发生丢失. 异步模式是一种基于偏移量的主从复制,实现原理是:主库开启binlog功能并授权从库连接主库,从库通过chan

sql执行效率,半同步复制

(1)尽量选择较小的列: (2)将where中用的比较频繁的字段建立索引: (3)select中避免使用*: (4)避免在索引列上使用计算.not in和<>等操作: (5)当只需要一行数据时候使用limit1: (6)保证单表数据不超过200w,实时分割表: 针对查询较慢的语句,可以使用explain来分析该语句具体的执行情况. sql语句应考虑哪些安全性? (1)少使用root账户,应该为不同的动作分配不同的账户: (2)sql执行出错后,不能把数据库中显示的出错信息,直接展示给用户.防止

mysql主从之半同步复制和lossless无损复制

一 MySQL 的三种复制方式 1.1 简介 asynchronous 异步复制 fully synchronous 全同步复制 Semisynchronous 半同步复制 从MySQL5.5 开始,MySQL 以插件的形式支持半同步复制. 1.2 异步复制(Asynchronous replication) MySQL 默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash 掉了,此时主上已经提交的事务可

MySQL 半同步复制模式说明及配置示例 - 运维小结

MySQL主从复制包括异步模式.半同步模式.GTID模式以及多源复制模式,默认是异步模式 (如之前详细介绍的mysql主从复制).所谓异步模式指的是MySQL 主服务器上I/O thread 线程将二进制日志写入binlog文件之后就返回客户端结果,不会考虑二进制日志是否完整传输到从服务器以及是否完整存放到从服务器上的relay日志中,这种模式一旦主服务(器)宕机,数据就可能会发生丢失. 异步模式是一种基于偏移量的主从复制,实现原理是: 主库开启binlog功能并授权从库连接主库,从库通过cha

mysql5.7.19的半同步复制问题分享

=== 异步复制(Asynchronous replication) MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整. 全同步复制(Fully synchronous replication) 指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端.因为需要等待所有从库执行完该事

mysql5.6 semi replication 半同步复制配置

--###半同步配置--1.插件位置mysql> show variables like 'plugin_dir' -> ;+---------------+------------------------------+| Variable_name | Value |+---------------+------------------------------+| plugin_dir | /usr/local/mysql/lib/plugin/ |+---------------+----

InnoSQL HA Suite的实现原理与配置说明 InnoSQL的VSR功能Virtual Sync Replication MySQL 5.5版本引入了半同步复制(semi-sync replicaiton)的功能 MySQL 5.6支持了crash safe功能

InnoSQL HA Suite的实现原理与配置说明  InnoSQL的VSR功能Virtual Sync Replication MySQL 5.5版本引入了半同步复制(semi-sync replicaiton)的功能 MySQL 5.6支持了crash safe功能 http://www.innomysql.net/article/7403.html Virtual Sync Replication 搭建一个MySQL数据库的复制(replication)环境是相当简单的,这点是MySQL

第四阶段 (七)MySQL REPLICATION(主从复制、半同步复制、复制过滤)

Linux运维 第四阶段 (七)MySQL REPLICATION(主从复制.半同步复制.复制过滤) 一.MySQL Replication相关概念: 1.复制的作用:辅助实现备份:高可用HA:异地容灾:分摊负载(scaleout):rw-spliting(mysql proxy工作在应用层). 2.master有多个CPU允许事务并行执行,但往二进制日志文件只能一条条写:slave比master要慢:master-slave默认异步方式传送. 3.半同步:仅负责最近一台slave同步成功,其它