一、 MGR介绍
MySQL Group Replication(简称MGR)是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决方案。MySQL组复制提供了高可用、高扩展、高可靠的MySQL集群服务。
1)高一致性,基于原生复制及paxos协议的组复制技术,并以插件的方式提供,提供一致数据安全保证;
2)高容错性,只要不是大多数节点坏掉就可以继续工作,有自动检测机制,当不同节点产生资源争用冲突时,不会出现错误,按照先到者优先原则进行处理,并且内置了自动化脑裂防护机制;
3)高扩展性,节点的新增和移除都是自动的,新节点加入后,会自动从其他节点上同步状态,直到新节点和其他节点保持一致,如果某节点被移除了,其他节点自动更新组信息,自动维护新的组信息;
4)高灵活性,有单主模式和多主模式,单主模式下,会自动选主,所有更新操作都在主上进行;多主模式下,所有server都可以同时处理更新操作。
MGR是MySQL数据库未来发展的一个重要方向。
1、 MGR基础结构要求
1)引擎必须为innodb,因为需事务支持在commit时对各节点进行冲突检查
2)每个表必须有主键,在进行事务冲突检测时需要利用主键值对比
3)必须开启binlog且为row格式
4)开启GTID,且主从状态信息存于表中(–master-info-repository=TABLE 、–relay-log-info-repository=TABLE),–log-slave-updates打开
5)一致性检测设置–transaction-write-set-extraction=XXHASH64
2、 MGR使用限制
1)RP和普通复制binlog校验不能共存,需设置–binlog-checksum=none
2)不支持gap lock(间隙锁),隔离级别需设置为read_committed
3)不支持对表进行锁操作(lock /unlock table),不会发送到其他节点执行 ,影响需要对表进行加锁操作的情况,列入mysqldump全表备份恢复操作
4)不支持serializable(序列化)隔离级别
5)DDL语句不支持原子性,不能检测冲突,执行后需自行校验是否一致
6)不支持外键:多主不支持,单主模式不存在此问题
7)最多支持9个节点:超过9台server无法加入组
二、 MGR环境准备
1、 数据库服务器规划
2、 在三台主机上设置hostname和IP映射
[root@xuegod140 ~]# vim /etc/hosts #120/130/140都设置hosts文件
192.168.2.120 xuegod120.com
192.168.2.130 xuegod130.com
192.168.2.140 xuegod140.com
注释:这里的hostname必须和hostname文件里写的一致
三、 创建复制环境
1、 xuegod120复制环境配置
1) 修改my.cnf文件
server_id = 100 #服务ID
gtid_mode = ON #全局事务
enforce_gtid_consistency = ON #强制GTID的一致性
master_info_repository = TABLE #将master.info元数据保存在系统表中
relay_log_info_repository = TABLE #将relay.info元数据保存在系统表中
binlog_checksum = NONE #禁用二进制日志事件校验
log_slave_updates = ON #级联复制
log_bin = binlog #开启二进制日志记录
binlog_format = ROW #以行的格式记录
transaction_write_set_extraction = XXHASH64 #使用哈希算法将其编码为散列
loose-group_replication_group_name = ‘ce9be252-2b71-11e6-b8f4-00212844f856’ #加入的组名,可以自定义,格式是这种就行,三台主机需要一致
loose-group_replication_start_on_boot = off #不自动启用组复制集群
loose-group_replication_local_address = ‘xuegod120.com:33061’ #以本机端口33061接受来自组中成>员的传入连接,这里的名字需要些hostname文件里面的名字
loose-group_replication_group_seeds = ‘xuegod120.com:33061, xuegod130.com:33062, xuegod140.com:33063’ #组中成员访问表
loose-group_replication_bootstrap_group = off #不启用引导组
保存并重启服务
注释:这里可以先不重启mysql服务,避免数据库会将操作记录到二进制日志文件,如果这里重启了mysqld服务,那么可以进入mysql关闭日志记录
mysql> set sql_log_bin=0;或off
2) 建立复制账号
[root@xuegod120 ~]# mysql -uroot -p123456 -A
mysql> set sql_log_bin=0; #这里上面如果没有重启mysql服务,不需要这一步操作
mysql> grant replication slave on . to repl@‘192.168.2.%’ identified by ‘123456’;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
3) 重启mysql服务,并构建group replication集群
[root@xuegod120 ~]# systemctl restart mysqld
[root@xuegod120 ~]# mysql -uroot -p123456 -A
mysql> change master to master_user=‘repl’,master_password=‘123456’ for channel ‘group_replication_reconvery’;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
4) 安装group replication插件
mysql> install plugin group_replication soname ‘group_replication.so’;
Query OK, 0 rows affected (0.27 sec)
5) 查看mysql支持的group repliation插件
mysql> show plugins;
6) 设置group replication引导启动
设置group_replication_bootstrap_group为ON是为了标示以后加入集群的服务器以这台服务器为基准,以后加入的就不需要设置。
mysql> set global group_replication_bootstrap_group=on;
Query OK, 0 rows affected (0.00 sec)
7) 开启group replication
作为首个MGR集群首个节点
mysql> start group_replication;
Query OK, 0 rows affected (2.26 sec)
8) 关闭group replication引导
mysql> set global group_replication_bootstrap_group=off;
Query OK, 0 rows affected (0.00 sec)
9) 查询MGR集群的信息
我们通过查询表来获取信息,因为my.cnf配置文件里面定义了将信息写入到表中
mysql> select * from performance_schema.replication_group_members;
注释:状态显示online,表示在线。
10) 创建测试数据库
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed
mysql> create table t1 (id int primary key,name varchar(20));
Query OK, 0 rows affected (0.18 sec)
mysql> insert into t1 values (1,‘AA’);
Query OK, 1 row affected (0.20 sec)
mysql> select * from t1;
±—±-----+
| id | name |
±—±-----+
| 1 | AA |
±—±-----+
1 row in set (0.00 sec)
11) 查询二进制日志文件
mysql> show binlog events;
2、 xuegod130复制环境配置
1) 修改my.cnf配置文件
#Group Replication
server_id = 101 #注意服务ID不一样
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
log_bin = binlog
binlog_format= ROW
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = ‘ce9be252-2b71-11e6-b8f4-00212844f856’
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = ‘xuegod130.com:33062’
loose-group_replication_group_seeds = ‘xuegod120.com:33061, xuegod130.com:33062, xuegod140.com:33063’
loose-group_replication_bootstrap_group = off
保存重启mysql服务
[root@xuegod130 ~]# systemctl restart mysqld
2) 创建复制账号,并构建group replication集群
注意:这里记得关闭二进制日志记录,因为上面重启服务了
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on . to repl@‘192.168.2.%’ identified by ‘123456’;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to master_user=‘repl’,master_password=‘123456’ for channel ‘group_replication_recovery’;
Query OK, 0 rows affected, 2 warnings (0.11 sec)
3) 安装group replication插件
mysql> install PLUGIN group_replication SONAME ‘group_replication.so’;
Query OK, 0 rows affected (0.27 sec)
4) 将实例添加到之前的复制组,并开启组复制
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected, 1 warning (5.90 sec)
5) 查看复制组的状态
mysql> select * from performance_schema.replication_group_members;
6) 查看数据库和表是否同步过来
mysql> show databases;
±-------------------+
| Database |
±-------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
±-------------------+
5 rows in set (0.03 sec)
mysql> use test
Database changed
mysql> select * from t1;
±—±-----+
| id | name |
±—±-----+
| 1 | AA |
±—±-----+
1 row in set (0.00 sec)
3、 xuegod140复制组的配置
1) 修改配置文件
#Group Replication
server_id = 102 #注意服务id不一样
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
log_bin = binlog
binlog_format= ROW
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = ‘ce9be252-2b71-11e6-b8f4-00212844f856’
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = ‘xuegod140.com:33063’
loose-group_replication_group_seeds =‘xuegod120.com:33061, xuegod130.com:33062, xuegod140.com:33063’
loose-group_replication_bootstrap_group = off
保存重启mysqld服务
[root@xuegod140 ~]# systemctl restart mysqld
2) 创建复制账号,并构建组复制集群
[root@xuegod140 ~]# mysql -uroot -p123456 -A
mysql> set SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on . to repl@‘192.168.2.%’ identified by ‘123456’;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> set SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to master_user=‘repl’,master_password=‘123456’ for channel ‘group_replication_recovery’;
Query OK, 0 rows affected, 2 warnings (0.16 sec)
3) 安装组复制集群插件
mysql> install PLUGIN group_replication SONAME ‘group_replication.so’;
Query OK, 0 rows affected (0.23 sec)
4) 添加实例到复制组,并启动组复制集群
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected, 1 warning (3.31 sec)
5) 查看组复制集群状态
mysql> select * from performance_schema.replication_group_members;
到此,单主节点的集群就搭建完毕!
4、 查看三台集群的状态
1) xuegod120-master的read_only状态
master的只读模式是关闭的,说明是可以写入数据
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | OFF |
| super_read_only | OFF |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.01 sec)
2) xuegod130的read_only状态
xuegod130的只读模式是开启,说明只能读取数据
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | ON |
| super_read_only | ON |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.01 sec)
3) xuegod140的read_only状态
同样xuegod140的只读模式也是开启
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | ON |
| super_read_only | ON |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.00 sec)
4) 我们可以进行测试
在xuegod120上插入数据(发现可以插入数据)
mysql> use test;
Database changed
mysql> insert into t1 values (2,‘BB’);
Query OK, 1 row affected (0.01 sec)
mysql> select * from t1;
±—±-----+
| id | name |
±—±-----+
| 1 | AA |
| 2 | BB |
±—±-----+
2 rows in set (0.00 sec)
在xuegod130和140上插入数据(发现报错,无法插入)
mysql> use test;
Database changed
mysql> insert into t1 values (3,‘CC’);
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannotexecute this statement
总结:MGR集群搭建完毕后,只能有一个写入的服务器,其他都是读取的服务器
5、 模拟主服务器挂掉,测试salve服务器能否接管
[root@xuegod120 ~]# systemctl stop mysqld
1) 先查看两台slave的组复制集群状态
mysql> select * from performance_schema.replication_group_members;
发现只能下两个slave服务器,主的已经没有了
2) 查看两台slave的read_only状态
xuegod130的read_only状态变更为关闭状态(可以写入数据)
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | OFF |
| super_read_only | OFF |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.00 sec)
xuegod140服务器的read_only状态还是开启的(只读)
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | ON |
| super_read_only | ON |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.00 sec)
总结:当master服务器挂掉后,其他两台slave服务器会通过选举,自动接管作为主服务器,代理员master服务器的业务,进行读写
6、 启动模拟故障的master服务器,查看能否自动加入集群
1) 查看组复制的状态
这里发现是offline状态(离线状态)
mysql> select * from performance_schema.replication_group_members;
±--------------------------±----------±------------±------------±-------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
±--------------------------±----------±------------±------------±-------------+
| group_replication_applier | | | NULL | OFFLINE |
±--------------------------±----------±------------±------------±-------------+
1 row in set (0.00 sec)
2) 开启组复制集群,再次查看状态
mysql> start group_replication;
Query OK, 0 rows affected (3.24 sec)
mysql> select * from performance_schema.replication_group_members;
注释:这里虽然看到已经加入到组复制集群,但是状态显示recovering
3) 加入组复制集群,后查看read_only状态
发现已经自动开启(只读状态)
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | ON |
| super_read_only | ON |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.00 sec)
4) 一段时间后,再次查看组复制集群状态,发现变更为ERROR
6) 故障解决办法
重新构建组复制集群,重启组复制集群即可
mysql> change master to master_user=‘repl’,master_password=‘123456’ for channel ‘group_replication_recovery’;
Query OK, 0 rows affected, 2 warnings (0.11 sec)
mysql> stop group_replication;
Query OK, 0 rows affected (1.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected (2.92 sec)
mysql> select * from performance_schema.replication_group_members;
四、 多主模式(multi-primary模式)
1、该模式启用需设置两个参数
group_replication_single_primary_mode=0 #这个参数很好理解,就是关闭单master模式
group_replication_enforce_update_everywhere_checks=1 #这个参数设置多主模式下各个节点严格一致性检查
2、 默认启动的都是单master模式,其他节点都设置了read_only、super_read_only这两个参数,需要修改这两个配置
3、 完成上面的配置后就可以执行多点写入了,多点写入会存在冲突检查,这耗损性能挺大的,官方建议采用网络分区功能,在程序端把相同的业务定位到同一节点,尽量减少冲突发生几率。
4、单主模式改多主模式方法
在原来单主模式的主节点执行操作如下
我们这里因为刚刚做了故障模拟,所以现在的主节点是xuegod130服务器
1) 在单主模式执行如下操作
mysql> stop group_replication;
Query OK, 0 rows affected (9.30 sec)
mysql> set global group_replication_single_primary_mode=off;
Query OK, 0 rows affected (0.00 sec)
mysql> set global group_replication_enforce_update_everywhere_checks=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected, 1 warning (2.02 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)
2) 在其他节点执行如下操作
xuegod120上
mysql> stop GROUP_REPLICATION;
Query OK, 0 rows affected (9.33 sec)
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> set global group_replication_single_primary_mode=off;
Query OK, 0 rows affected (0.00 sec)
mysql> set global group_replication_enforce_update_everywhere_checks=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected, 1 warning (5.77 sec)
xuegod140上
mysql> stop GROUP_REPLICATION;
Query OK, 0 rows affected (9.33 sec)
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> set global group_replication_single_primary_mode=off;
Query OK, 0 rows affected (0.00 sec)
mysql> set global group_replication_enforce_update_everywhere_checks=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected, 1 warning (5.77 sec)
4) 查看各个节点的read_only状态
xuegod120:(关闭状态,可以写入)
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | OFF |
| super_read_only | OFF |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.01 sec)
xuegod130:(关闭状态,可以写入)
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | OFF |
| super_read_only | OFF |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.00 sec)
xuegod140:(关闭状态,可以写入)
mysql> show variables like “%read_only%”;
±----------------------±------+
| Variable_name | Value |
±----------------------±------+
| innodb_read_only | OFF |
| read_only | OFF |
| super_read_only | OFF |
| transaction_read_only | OFF |
| tx_read_only | OFF |
±----------------------±------+
5 rows in set (0.00 sec)
5) 在各个节点上,插入数据,进行测试
xuegod120:
mysql> use test
Database changed
mysql> insert into t1 values (3,‘CC’);
Query OK, 1 row affected (0.20 sec)
mysql> select * from t1;
±—±-----+
| id | name |
±—±-----+
| 1 | AA |
| 2 | BB |
| 3 | CC |
±—±-----+
3 rows in set (0.00 sec)
xuegod130:
mysql> use test
Database changed
mysql> insert into t1 values (4,‘DD’);
Query OK, 1 row affected (0.01 sec)
mysql> select * from t1;
±—±-----+
| id | name |
±—±-----+
| 1 | AA |
| 2 | BB |
| 3 | CC | #复制也OK
| 4 | DD |
±—±-----+
4 rows in set (0.00 sec)
xuegod140:
mysql> use test;
Database changed
mysql> insert into t1 values (5,‘EE’);
Query OK, 1 row affected (0.01 sec)
mysql> select * from t1;
±—±-----+
| id | name |
±—±-----+
| 1 | AA |
| 2 | BB |
| 3 | CC |
| 4 | DD |
| 5 | EE |
±—±-----+
5 rows in set (0.00 sec)