在谈这个特性之前,我们先来看看MySQL的复制架构衍生史。
在2000年,MySQL 3.23.15版本引入了Replication。Replication作为一种准实时同步方式,得到广泛应用。这个时候的Replicaton的实现涉及到两个线程,一个在Master,一个在Slave。Slave的I/O和SQL功能是作为一个线程,从Master获取到event后直接apply,没有relay log。这种方式使得读取event的速度会被Slave replay速度拖慢,当主备存在较大延迟时候,会导致大量binary log没有备份到Slave端。
在2002年,MySQL 4.0.2版本将Slave端event读取和执行独立成两个线程(IO线程和SQL线程),同时引入了relay log。IO线程读取event后写入relay log,SQL线程从relay log中读取event然后执行。这样即使SQL线程执行慢,Master的binary log也会尽可能的同步到Slave。当Master宕机,切换到Slave,不会出现大量数据丢失。
在2010年MySQL 5.5版本之前,一直采用的是这种异步复制的方式。主库的事务执行不会管备库的同步进度,如果备库落后,主库不幸crash,那么就会导致数据丢失。于是在MySQL在5.5中就顺其自然地引入了半同步复制,主库在应答客户端提交的事务前需要保证至少一个从库接收并写到relay log中。那么半同步复制是否可以做到不丢失数据呢?下面分析。
在2016年,MySQL在5.7.17中引入了一个全新的技术,称之为InnoDB Group Replication。目前官方MySQL 5.7.17基于Group replication的全同步技术已经问世,全同步技术带来了更多的数据一致性保障。相信是未来同步技术一个重要方向,值得期待。MySQL 5.7 Group Replication
主从复制机制:
主主复制机制:组复制之多主模式
组复制是一种可用于实现容错系统的技术。 复制组是一个通过消息传递相互交互的 server 集群。通信层提供了原子消息(atomicmessage)和完全有序信息交互等保障机制,实现了基于复制协议的多主更新
复制组由多个 server成员构成,并且组中的每个 server 成员可以独立地执行事务。但所有读写(RW)事务只有在冲突检测成功后才会提交。只读(RO)事务不需要在冲突检测,可以立即提交。句话说,对于任何 RW 事务,提交操作并不是由始发 server 单向决定的,而是由组来决定是否提交。准确地说,在始发 server 上,当事务准备好提交时,该 server 会广播写入值(已改变的行)和对应的写入集(已更新的行的唯一标识符)。然后会为该事务建立一个全局的顺序。最终,这意味着所有 server 成员以相同的顺序接收同一组事务。因此,所有 server 成员以相同的顺序应用相同的更改,以确保组内一致。
组复制主要用于数据库集群中,多主数据同步,和主从同步不同,每个主库的数据保持一致,都可以接受写操作
A. 当Master上开启半同步复制的功能时,至少应该有一个Slave开启其功能。此时,一个线程在Master上提交事务将受到阻塞,直到得知一个已开启半同步复制功能的Slave已收到此事务的所有事件,或等待超时。
B. 当Slave主机连接到Master时,能够查看其是否处于半同步复制的机制。
C. 当一个事务的事件都已写入其relay-log中且已刷新到磁盘上,Slave才会告知已收到;这取决于sync_relay_log参数。
D. 如果等待超时,也就是Master没被告知已收到,此时Master会自动转换为异步复制的机制。当至少一个半同步的Slave赶上了,Master与其Slave自动转换为半同步复制的机制。
E. 半同步复制的功能要在Master,Slave都开启,半同步复制才会起作用;否则,只开启一边,它依然为异步复制。
首先,安装半同步模块并启动,此模块根据MySQL安装方式不同位置也可能不太一样。如果是二进制安装,则会在MySQL安装目录的./lib/plugin/下存放。建议无论主从都安装master & slave模块,以免高可用模式下遗忘。
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
查看半同步相关的状态信息,如下:
mysql> show global variables like '%semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+-------+
6 rows in set (0.00 sec)
其中rpl_semi_sync_master_enabled参数表示Master是否开启了半同步协议,参数rpl_semi_sync_master_timeout表示与Slave半同步协议通信超时时间,如果超过这个时间则自动降级为异步复制。
下面开启Master上的半同步复制协议,并且调小了超时时间为2s,一旦有一次超时自动降级为异步。
mysql> set global rpl_semi_sync_master_enabled = 1;
mysql> set global rpl_semi_sync_master_timeout = 2000;
以上内容要想永久有效需要写到配置文件中,生产需写入配置文件,避免重启后半同步失效。
rpl_semi_sync_master_enabled = 1;
rpl_semi_sync_master_timeout = 2000;
首先,安装半同步模块并启动。
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled = 1;
mysql> show global variables like '%semi_sync_slave%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
2 rows in set (0.00 sec)
从节点需要重新连接主服务器半同步才会生效。
mysql> stop slave io_thread;
mysql> start slave io_thread;
PS:如果想卸载异步模块就使用uninstall即可。
此时,半同步复制应该已经正常工作了。可以在Master上查看半同步相关状态变量。
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 | 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 |
| Rpl_semi_sync_slave_status | OFF |
+--------------------------------------------+-------+
15 rows in set (0.00 sec)
现在半同步已经正常工作了,主要看Rpl_semi_sync_master_clients是否不为0,Rpl_semi_sync_master_status是否为ON。其中Rpl_semi_sync_master_clients=1表示此时有一个Slave以半同步协议连接Master。如果Rpl_semi_sync_master_status为OFF,说明出现了网络延迟或Slave IO线程异常,导致自动切换为异步复制了。
那么可以验证一下半同步超时,是否会自动降为异步工作。可以在Slave上停掉半同步协议,然后在Master上创建数据库看一下能不能复制到Slave上。
mysql> set global rpl_semi_sync_slave_enabled = 0;
mysql> stop slave io_thread;
mysql> start slave io_thread;
mysql> create database dbtest;
Query OK, 1 row affected (2.01 sec)
mysql> create database dbtest01;
Query OK, 1 row affected (0.01 sec)
创建第一个数据库花了2.01秒,而我们前面设置的超时时间是2秒,而创建第二个数据库花了0.01秒,由此得出结论是超时转换为异步传送。可以在Master上查看半同步相关的参数值Rpl_semi_sync_master_clients和Rpl_semi_sync_master_status是否正常。
mysql> show global status like '%semi%';
+--------------------------------------------+-------------+
| Variable_name | Value |
+--------------------------------------------+-------------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 294 |
| Rpl_semi_sync_master_net_wait_time | 588 |
| 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 | 317 |
| Rpl_semi_sync_master_tx_wait_time | 635 |
| 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 |
| Rpl_semi_sync_slave_status | OFF |
| Rpl_status | AUTH_MASTER |
+--------------------------------------------+-------------+
16 rows in set (0.00 sec)
可以看到都自动关闭了,需要注意一点的是,当Slave开启半同步后,或者当主从之间网络延迟恢复正常的时候,半同步复制会自动从异步复制又转为半同步复制,还是相当智能的。
另外,参数Rpl_semi_sync_master_no_times表示主库启动切换为异步的次数,可以看到我们这里模拟了一次切换,值加1了。参数Rpl_semi_sync_master_no_tx表示降级为异步后产生的事务数,这里变为2了。需要注意的是,DDL一条语句执行成功就会加1,DML一个事务成功才会加1。这些参数都可以用来做监控使用。
另外个人在实际使用中还碰到一种情况从库IO线程有延迟时,主库会自动把半同步复制降为异步复制;当从库IO延迟没有时,主库又会把异步复制升级为半同步复制。可以进行压测模拟,但是此时查看Master的状态跟上面直接关闭Slave半同步有些不同,会发现Rpl_semi_sync_master_clients仍然等于1,而Rpl_semi_sync_master_status等于OFF。
MySQL双主复制模型如果配置出现问题,很有可能会导致主从数据不一致。单双主模型能做什么呢?可以分摊读的压力,但写数据同一时刻只能有一台。另外可以在双主模型下做高可用。
1)在两台服务器上各自建立一个具有复制权限的用户。
2)修改配置文件。
主服务器上配置
[mysqld]
server-id = 10
log-bin = mysql-bin
relay-log = relay-mysql
relay-log-index = relay-mysql.index
auto-increment-increment = 2
auto-increment-offset = 1
从服务器上配置
[mysqld]
server-id = 20
log-bin = mysql-bin
relay-log = relay-mysql
relay-log-index = relay-mysql.index
auto-increment-increment = 2
auto-increment-offset = 2
两台服务器都需要开启二进制日志和中继日志。对于Master设置主键自动增长auto-increment-offset起始值从1开始,auto-increment-increment步长为2,也就是auto_increment为奇数。而对于Slava自动增长从2开始,偏移为2,也就是auto_increment为偶数。这样才能避免两台服务器数据同步时出现主键冲突问题。
3)主从各自连接对方服务器CHANGE MASTER
4)主从服务器各自自动复制对方的Slave
对于MySQL的管理,percona toolkit工具可以说非常强大,建议使用。
其中percona toolkit的pt-table-checksum工具可以用来评估主从服务表中的数据是否一致,而pt-table-sync工具可以用来解决主从数据的不一致问题。使用这些工具时在主服务器上操作,会主动去检测所有的从服务器。
https://www.cnblogs.com/zero-gg/p/9057092.html
原文出自http://www.ywnds.com/?p=3840