|
|
|
@ -0,0 +1,191 @@
|
|
|
|
|
# MySQl组复制
|
|
|
|
|
|
|
|
|
|
### 组复制部署
|
|
|
|
|
|
|
|
|
|
**环境准备**
|
|
|
|
|
至少需要3台服务器,每台服务器上已经完成MySQL 8.0安装
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
192.168.26.160 master
|
|
|
|
|
192.168.26.128 node1
|
|
|
|
|
192.168.26.130 node2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
组复制可以以单主或多主模式运行,默认是单主模式,这里选取192.168.26.160(主机名master)作为单主读写服务器,其他2台为只读服务器。
|
|
|
|
|
|
|
|
|
|
**查询主库uuid**
|
|
|
|
|
|
|
|
|
|
3台机器配置文件中的uuid需要一样,在主库使用select uuid()查询,使用主库的uuid即可
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
mysql> select uuid();
|
|
|
|
|
+--------------------------------------+
|
|
|
|
|
| uuid() |
|
|
|
|
|
+--------------------------------------+
|
|
|
|
|
| a71de24e-0bae-11f0-af42-000c29649a9e |
|
|
|
|
|
+--------------------------------------+
|
|
|
|
|
1 row in set (0.00 sec)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**修改配置文件**
|
|
|
|
|
|
|
|
|
|
组复制的事务传递是基于GTID的,且与部分引擎不兼容,因此需要修改相应的参数内容。
|
|
|
|
|
|
|
|
|
|
修改3台机器配置文件,新增下列参数:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
#----------------认证插件-----------------------
|
|
|
|
|
#8.0默认使用的认证插件需要ssl认证,这里修改了认证插件不使用ssl
|
|
|
|
|
default_authentication_plugin=mysql_native_password
|
|
|
|
|
|
|
|
|
|
#----------------Storage_engine----------------
|
|
|
|
|
# 组复制的数据必须存储在事务型引擎中。在多主模式下,事务冲突监测的机制是乐观型,即先执行事务,再检测冲突。如果有冲突则所有的成员都必须回滚,因此无法执行回滚的非事务型的存储引擎和组复制不兼容,需要禁用。
|
|
|
|
|
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
|
|
|
|
|
|
|
|
|
|
#----------------Replication----------------
|
|
|
|
|
server_id=1 #三台机器不一样
|
|
|
|
|
gtid_mode=on
|
|
|
|
|
enforce_gtid_consistency=on
|
|
|
|
|
binlog_checksum=none
|
|
|
|
|
log_bin=mysql-bin
|
|
|
|
|
log_slave_updates=on
|
|
|
|
|
binlog_format=row
|
|
|
|
|
|
|
|
|
|
#----------------Group replication----------------
|
|
|
|
|
plugin_load_add='group_replication.so'
|
|
|
|
|
group_replication_group_name="6afcf923-0ba5-11f0-8fad-000c29649a9e"
|
|
|
|
|
group_replication_start_on_boot=off # 在MySQL启动时不会自动启动组复制
|
|
|
|
|
group_replication_local_address= "192.168.26.160:33061" #修改成每个节点的ip即可
|
|
|
|
|
group_replication_group_seeds= "192.168.26.160:33061, 192.168.26.128:33061, 192.168.26.130:33061"
|
|
|
|
|
group_replication_bootstrap_group=off # 设置是否引导组服务(即创建一个组),一定要设置为off,否则每次重启都会引导一个新组出来。
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**重启服务**
|
|
|
|
|
|
|
|
|
|
重启服务并通过show plugins命令确认组复制插件已安装:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
mysql> show plugins;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**设置分布式恢复服务的用户凭证**
|
|
|
|
|
当有新成员加入组复制时,会通过分布式恢复进程(Distributed Recovery Process)来同步数据。分布式恢复进程会先找一个数据的捐赠者(Donor),并通过一个名为group_replication_reocvery的通道将捐赠者binlog中的事务发送给新成员。在这里需要一个授权用户凭证来建立分布式恢复的连接。这个用户在所有的组成员上都必须存在。
|
|
|
|
|
|
|
|
|
|
在主库执行下列命令创建连接用户:
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
set sql_log_bin=0;
|
|
|
|
|
create user repuser@'%' identified with 'mysql_native_password' by 'reppassword';
|
|
|
|
|
grant replication slave on *.* to repuser@'%';
|
|
|
|
|
grant connection_admin on *.* to repuser@'%';
|
|
|
|
|
grant backup_admin on *.* to repuser@'%';
|
|
|
|
|
flush privileges;
|
|
|
|
|
set sql_log_bin=1;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
创建好用户后,将用户凭证指定为分布式恢复进程使用:
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
change master to master_user='repuser', master_password='reppassword' for channel 'group_replication_recovery';
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**组复制引导**
|
|
|
|
|
第一次启动组复制称作引导,引导会创建一个组出来。通过group_replication_bootstrap_group参数来控制引导动作。引导组复制必须由单一服务器完成且只需要执行一次。如果group_replication_bootstrap_group设置为on,则每次重启都会创建出一个同名新组,这也是前面参数中将其设置为off的原因。
|
|
|
|
|
|
|
|
|
|
执行下列命令引导组复制:
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
set global group_replication_bootstrap_group=on;
|
|
|
|
|
start group_replication;
|
|
|
|
|
set global group_replication_bootstrap_group=off;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**注意**:只有在第一次启动组复制时,才需要设置group_replication_bootstrap_group,后续成员加入时都不能设置此变量,否则会产生经典的分布式系统问题 --- 脑裂(split brain)。
|
|
|
|
|
|
|
|
|
|
一旦start group_replication;语句成功返回后,组复制就成功启动了,可以通过下列语句确认引导结果:
|
|
|
|
|
|
|
|
|
|
------------------------------------------------
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
select * from performance_schema.replication_group_members;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
查询结果显示member_state为online,member_role为primary,说明组复制已经引导成功了。
|
|
|
|
|
|
|
|
|
|
在主库运行一些事务,mysql8.0默认开始事务:
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
create database test;
|
|
|
|
|
use test;
|
|
|
|
|
create table t1(id int auto_increment primary key);
|
|
|
|
|
insert into t1 values(null);
|
|
|
|
|
insert into t1 values(null);
|
|
|
|
|
insert into t1 values(null);
|
|
|
|
|
commit;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
然后可以通过show binlog events in '日志名';查看二进制日志中的内容,可以看到日志已写入二进制日志,此时主库可以作为捐赠者(Donor),可以将这些事务变更同步给后加入的成员。
|
|
|
|
|
|
|
|
|
|
**将其他成员加入组复制**
|
|
|
|
|
完成前面操作后,已经创建出了一个组,并且其中已有1台主库在运行了,下面需将另外两个成员也加入组复制。
|
|
|
|
|
|
|
|
|
|
新成员加入组时会有一个数据恢复的动作,如果加入时组内数据已经很大了,那么这个过程可能会耗费很长时间,并且如果主库purge过二进制日志,那么恢复会失败。此时应使用备份恢复工具(mysqldump/xtrabackup等)将待加入的成员数据状态还原至离主库较近的时间点,以缩短加入后的数据恢复时间。
|
|
|
|
|
|
|
|
|
|
本示例是全新环境,数据变更很少,且主库具有所有变更的日志,可以将新成员直接加入,由分布式恢复进程来同步数据。
|
|
|
|
|
|
|
|
|
|
所有从服务器重启服务并创建分布式恢复凭证
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
set sql_log_bin=0;
|
|
|
|
|
create user repuser@'%' identified with 'mysql_native_password' by 'reppassword';
|
|
|
|
|
grant replication slave on *.* to repuser@'%';
|
|
|
|
|
grant connection_admin on *.* to repuser@'%';
|
|
|
|
|
grant backup_admin on *.* to repuser@'%';
|
|
|
|
|
flush privileges;
|
|
|
|
|
set sql_log_bin=1;
|
|
|
|
|
change master to master_user='repuser', master_password='reppassword' for channel 'group_replication_recovery';
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
启动组复制,加入组
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
# 注意不需要再引导组了
|
|
|
|
|
mysql> start group_replication;
|
|
|
|
|
mysql> select * from performance_schema.replication_group_members;
|
|
|
|
|
------+--------------+-------------+----------------+----------------------------+
|
|
|
|
|
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
|
|
|
|
|
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
|
|
|
|
|
| group_replication_applier | 0a7b9277-0bab-11f0-8d9d-000c29649a9e | master | 3306 | ONLINE | PRIMARY | 8.0.41 | XCom |
|
|
|
|
|
| group_replication_applier | aad69d1c-0bab-11f0-bee6-000c29f67e93 | node2 | 3306 | ONLINE | SECONDARY | 8.0.41 | XCom |
|
|
|
|
|
| group_replication_applier | b0021552-0baa-11f0-bd9f-000c29b36e90 | node1 | 3306 | ONLINE | SECONDARY | 8.0.41 | XCom |
|
|
|
|
|
+---------------------------+--------------------------------------+-------------+-------
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
此时我们看到第二和第三个成员已经成功加入组复制,成员角色为secondary,状态为online。
|
|
|
|
|
|
|
|
|
|
### 组复制容错测试
|
|
|
|
|
|
|
|
|
|
为了测试组复制的容错,在主库上直接杀掉MySQL进程(非正常关闭),模拟服务器宕机。
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
killall mysqld
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**观察角色切换**
|
|
|
|
|
|
|
|
|
|
在原来的从库上查询成员状态(kill命令在两次查询之间执行),注意此时服务器node1的角色自动从secondary变为primay,表示其被提升为新的主库:
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
select * from performance_schema.replication_group_members;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**原主库重新加入组复制**
|
|
|
|
|
|
|
|
|
|
将原主库重新启动,并加入组复制,注意此时宕机的主库将以从库的身份加入组复制(不会自动恢复主库身份),主库依然是上次切换的node1
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
#主库运行下列指令
|
|
|
|
|
start group_replication;
|
|
|
|
|
select * from performance_schema.replication_group_members;
|
|
|
|
|
```
|
|
|
|
|
|