MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread, SQL
thread)运行在从节点,如下图所示:
当从节点连接主节点时,主节点会创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,甚至在发动给从节点之前,锁会被释放。
当从节点上执行
start slave
命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log中。
SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。
对于每一个主从连接,都需要三个进程来完成。当主节点有多个从节点时,主节点会为每一个当前连接的从节点建一个binary log dump 进程,而每个从节点都有自己的I/O进程,SQL进程。从节点用两个线程将从主库拉取更新和执行分成独立的任务,这样在执行同步数据任务的时候,不会降低读操作的性能。比如,如果从节点没有运行,此时I/O进程可以很快从主节点获取更新,尽管SQL进程还没有执行。如果在SQL进程执行之前从节点服务停止,至少I/O进程已经从主节点拉取到了最新的变更并且保存在本地relay日志中,当服务再次起来之后,就可以完成数据的同步。
要实施复制,首先必须打开Master 端的binary log(bin-log)功能,否则无法实现。
因为整个复制过程实际上就是Slave 从Master 端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。如下图所示:
复制的基本过程如下:
异步模式如下图所示,这种模式下,主节点不会主动push bin log到从节点,这样有可能导致failover的情况下,也许从节点没有即时地将最新的bin log同步到本地。
这种模式下主节点只需要接收到其中一台从节点的返回信息,就会commit;否则需要等待直到超时时间然后切换成异步模式再提交;这样做的目的可以使主从数据库的数据延迟缩小,可以提高数据安全性,确保了事务提交后,binlog至少传输到了一个从节点上,但不能保证从节点将此事务更新到db中。性能上会有一定的降低,响应时间会变长。如下图所示:
半同步模式不是mysql内置的,从mysql 5.5开始集成,需要master 和slave 安装插件开启半同步模式。
全同步模式是指主节点和从节点全部执行了commit并确认才会向客户端返回成功。
两台rhel7.5的虚拟机,一台作为master,一台作为slave。
主机名(IP) | 角色 |
---|---|
server1 | master |
server2 | slave |
我们这里分别通过传统的基于日志点的主从复制、基于GTID的主从复制分别实现异步复制。
[root@server1 ~]# ls
mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
[root@server1 ~]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
[root@server1 ~]# ls
mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
mysql-community-client-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm
mysql-community-devel-5.7.24-1.el7.x86_64.rpm
mysql-community-embedded-5.7.24-1.el7.x86_64.rpm
mysql-community-embedded-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-embedded-devel-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-minimal-debuginfo-5.7.24-1.el7.x86_64.rpm
mysql-community-server-5.7.24-1.el7.x86_64.rpm
mysql-community-server-minimal-5.7.24-1.el7.x86_64.rpm
mysql-community-test-5.7.24-1.el7.x86_64.rpm
我们这里安装mysql只需要一些必要的包即可,即下面这五个:
[root@server1 ~]# yum install -y mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm
因为要实现主从复制,所以server2也需要安装这些包:
[root@server1 ~]# scp mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm [email protected]:
[root@server1 ~]# systemctl start mysqld
[root@server1 ~]# grep password /var/log/mysqld.log
2019-07-29T02:17:59.567048Z 1 [Note] A temporary password is generated for root@localhost: dkgi%%xeo1=A
[root@server1 ~]# mysql_secure_installation
[root@server1 ~]# mysql -uroot -pWsp+123ld
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.24 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
[root@server1 ~]# vim /etc/my.cnf
文件末尾添加:
保存退出后记得重启服务:systemctl restart mysqld
mysql> CREATE USER 'repl'@'172.25.66.%' IDENTIFIED BY 'Wsp+123ld';
Query OK, 0 rows affected (0.02 sec)
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.25.66.%';
Query OK, 0 rows affected (0.01 sec)
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 615 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@server2 ~]# yum install -y mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm
[root@server2 ~]# systemctl start mysqld
[root@server2 ~]# grep pass /var/log/mysqld.log
2019-07-29T02:46:44.242354Z 1 [Note] A temporary password is generated for root@localhost: 2pH,kaH)nI/w
[root@server2 ~]# mysql_secure_installation
这里与MASTER一致。
[root@server2 ~]# vim /etc/my.cnf
在文件最下写入一行:
server-id=2
[root@server2 ~]# systemctl restart mysqld
mysql> CHANGE MASTER TO MASTER_HOST='172.25.66.1',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='Wsp+123ld',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=615;
注意:这里的Master相关信息就是我们刚刚设置主库的相关信息,其中 MASTER_LOG_FILE和MASTER_LOG_POS是我们上面通过show master status;
查看到的。
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.66.1 # 查看是否是master
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 615
Relay_Log_File: server2-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes #这里IO线程、SQL线程运行,说明成功
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
如果这里Slave_IO_Running、Slave_IO_Running不全是Yes,请看这篇博客,有几种排错方法。
mysql> create database linux;
Query OK, 1 row affected (0.01 sec)
mysql> use linux;
Database changed
mysql> create table userlist(
-> username varchar(10) not null,
-> age int not null);
Query OK, 0 rows affected (0.18 sec)
mysql> insert into userlist values('mac',23);
Query OK, 1 row affected (0.02 sec)
mysql> select * from userlist;
+----------+-----+
| username | age |
+----------+-----+
| mac | 23 |
+----------+-----+
1 row in set (0.00 sec)
mysql> select * from linux.userlist;
+----------+-----+
| username | age |
+----------+-----+
| mac | 23 |
+----------+-----+
1 row in set (0.00 sec)
至此,我们就用传统的主从复制方法——基于日志点的主从复制实现了异步复制。
mysql数据库从5.6.5开始新增一种基于gtid的复制方式。gtid(global transaction id)是对于一个已提交事务的编号。gtid实际上是由uuid+tid组成的,其中uuid是mysql实例的一个标识,tid则代表了该实例上交的事务数量,并且随着事务的提交单调递增。
主从复制默认是通过pos(position)复制,就是说在日志文档里,将用户进行的每一项操作都进行编号(pos),每一个事件都有一个起始编号,一个终止编号,在配置主从复制节点时,要求其从master的pos开始同步数据库里面的数据,这也称作传统复制技术。
gtid就是类似pos的作用,不过它是整个mysql复制架构全局通用的,即在整个mysql冗余架构中,它们的日志文件里面事件的gtid的数值是一致的。
gtid是一个对于已提交的事物的编号,并且是一个全局唯一的编号。
通过gtid保证每个主库上提交的事务在集群中有一个唯一的id。这种方式强化了主备的一致性,故障恢复及其容错能力。
@ 在传统的复制里面,当发生故障,需要主从切换,需要找到binlog和pos点,然后将主节点指向新的主节点,相对来说比较麻烦,也容易出错。在MySQL 5.6里面,不用再找binlog和pos点,我们只需要知道主节点的ip,端口,以及账号密码就行,因为复制是自动的,MySQL会通过内部机制GTID自动找点同步。
@ 多线程复制(基于库),在MySQL 5.6以前的版本,slave的复制是单线程的。一个事件一个事件的读取应用。而master是并发写入的,所以延时是避免不了的。唯一有效的方法是把多个库放在多台slave,这样又有点浪费服务器。在MySQL 5.6里面,我们可以把多个表放在多个库,这样就可以使用多线程复制。
俩者都是日志文件里的一个标志,如果将整个mysql集群看作一个整体,pos就是局部的,gtid就是全局的。
gtid_mode=ON
enforce-gtid-consistency=true
[root@server1 ~]# systemctl restart mysqld
[root@server1 ~]# cat /var/lib/mysql/auto.cnf
[auto]
server-uuid=15d708f6-b1a7-11e9-9c82-525400d85f32
gtid_mode=ON
enforce-gtid-consistency=true
systemctl restart mysqld
mysql> stop slave;
Query OK, 0 rows affected (0.03 sec)
mysql> CHANGE MASTER TO
-> MASTER_HOST = '172.25.66.1',
-> MASTER_USER = 'repl',
-> MASTER_PASSWORD = 'Wsp+123ld',
-> MASTER_AUTO_POSITION = 1;
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.66.1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: server2-relay-bin.000002
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 576
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 15d708f6-b1a7-11e9-9c82-525400d85f32 # uuid与master一致
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
mysql> insert into linux.userlist values('hah',12);
Query OK, 1 row affected (0.03 sec)
mysql> select * from linux.userlist;
+----------+-----+
| username | age |
+----------+-----+
| mac | 23 |
| hah | 12 |
+----------+-----+
2 rows in set (0.00 sec)
我们这里实现Mysql的基于GTID的半同步复制实验。
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果挂掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。则半同步复制就解决数据丢失的问题。半同步最少有一个slave复制完成master的所有数据后才会进行下一步事务操作。
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.02 sec)
mysql> SET GLOBAL rpl_semi_sync_master_enabled = ON;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
1 row in set (0.00 sec)
mysql> show variables like '%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_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.00 sec)
这里可以看到,master的半同步已经开启,半同步的超时时间:10000ms(10s),我们在实际生产环境中为了保证数据完整性,用半同步的话,一般需要设置为无穷大;超时过后,默认变为异步复制。
mysql> show status like '%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 | 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)
可以看到| Rpl_semi_sync_master_status | ON |
,说明已经开启成功。
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%semi%';
+---------------------------------+-------+
| 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;
Query OK, 0 rows affected (0.02 sec)
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into linux.userlist values('nv',13);
Query OK, 1 row affected (10.03 sec)
mysql> insert into linux.userlist values('waaaa',43);
Query OK, 1 row affected (0.02 sec)
mysql> show status like '%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 | 0 |
| 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 | 0 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
可以看到,其中| Rpl_semi_sync_master_no_tx | 2 |
表示有两次没有半同步成功。
此时我们在从端查询不到新插入的数据。
mysql> select * from linux.userlist;
+----------+-----+
| username | age |
+----------+-----+
| mac | 23 |
| hah | 12 |
+----------+-----+
2 rows in set (0.00 sec)
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from linux.userlist;
+----------+-----+
| username | age |
+----------+-----+
| mac | 23 |
| hah | 12 |
| nv | 13 |
| waaaa | 43 |
+----------+-----+
4 rows in set (0.00 sec)
组复制分单主模式和多主模式,mysql 的复制技术仅解决了数据同步的问题。但是如果 master 宕机,意味着数据库管理员需要介入,应用系统可能需要修改数据库连接地址或者重启才能实现。
组复制在数据库层面上做到了,只要集群中大多数主机可用,则服务可用。
单主模型:从复制组众多个MYSQL节点中自动选举一个master节点,只有master节点可以写,其它节点自动设置为只读。当master节点故障时,会自动选举一个新的master节点,选举成功后,它将设置为可写,其它的slave将指向这个新的master。
多主模型:复制组中的任何一个节点都可以写,因此没有master和slave的概念,只要突然故障的节点的数量不太多这个多主模就能继续使用。
组复制由多个mysql服务器组成,并且组中的每一个mysql服务成员可以独立的执行事务。但是所有的读写事务只有在冲突检测成功后才会提交,只读事务不需要冲突检测,可以立即提交。
对于任何读写事务,提交操作并不是由始发服务单向决定的,而是由组来决定是否提交。
在始发mysql服务上,当事务准备好要提交时,该主机会广播写入值即已改变的行和对应的写入集及已更新的行的唯一标识符。然后会为该事务建立一个全局的顺序。最终,所有的server成员以相同的顺序接收同一组事务。所有的server成员以相同的顺序应用相同的更改,以保证组内一致。
这里需要增加一台slave节点。
主机名(IP) | 服务 |
---|---|
server1(172.25.66.1) | master |
server2(172.25.66.2) | slave |
server3(172.25.66.3) | slave |
1.由于在此实验之前做了mysql的其它相关应用,所以首先需要进行对数据库重新清理,以下2、3步为清理过程
2.查看server1上的uuid后面组复制时的配置文件需要用到
注意:这里需要的uuid和后面组中所有节点的uuid不能相同。
[root@server1 ~]# cat /var/lib/mysql/auto.cnf
[auto]
server-uuid=15d708f6-b1a7-11e9-9c82-525400d85f32
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# systemctl stop mysqld.service
[root@server1 mysql]# ls
auto.cnf client-key.pem ib_logfile1 mysql-bin.000002 public_key.pem
ca-key.pem ib_buffer_pool linux mysql-bin.index server-cert.pem
ca.pem ibdata1 mysql performance_schema server-key.pem
client-cert.pem ib_logfile0 mysql-bin.000001 private_key.pem sys
[root@server1 mysql]# rm -fr *
[root@server1 mysql]# ls
server_id=1
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 ##指定server必须为每个事务收集写集合,并使用哈希算法将其编码为散列
loose-group_replication_group_name="15d708f6-b1a7-11e9-9c82-525400d85f32" ##对创建的组命名,为我们之前的master的uuid
loose-group_replication_start_on_boot=off ##不自动启动组复制
loose-group_replication_local_address= "172.25.66.1:33061" ##本地的端口33061实现成员连接
loose-group_replication_group_seeds= "172.25.66.1:33061,172.25.66.2:33061,172.25.66.3:33061"
loose-group_replication_bootstrap_group=off ##是否自动引导组
loose-group_replication_ip_whitelist="127.0.0.1,172.25.66.0/24"
loose-group_replication_enforce_update_everywhere_checks=ON ##打开检查及其更新
loose-group_replication_single_primary_mode=OFF #设置组自动选择一个server来处理读写工作
[root@server1 mysql]# systemctl restart mysqld
[root@server1 mysql]# grep password /var/log/mysqld.log
mysql> alter user root@localhost identified by 'Wsp+123ld';
Query OK, 0 rows affected (0.03 sec)
mysql> SET SQL_LOG_BIN=0; ##首先在进行用户建立之前关闭二进制日志,建立好之后再打开
mysql> CREATE USER 'repl'@'%' identified by 'Wsp+123ld'; ##创建复制用户
mysql> select user from mysql.user; # 查看用户
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; #授予用户权限
mysql> FLUSH PRIVILEGES; ##刷新数据
mysql> SET SQL_LOG_BIN=1; ##开启日志
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='Wsp+123ld' FOR CHANNEL 'group_replication_recovery';
##设置如果要改变master时需要通过该通道group_replication_recovery给其master的用户名和密码
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so'; ##安装组复制插件
mysql> SET GLOBAL group_replication_bootstrap_group=ON; ##只在master上进行的操作,即自动引导组,当打开组复制之后将其再关闭
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
mysql> SHOW PLUGINS; ##查看组复制插件,是否成功
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ba729a62-b1c5-11e9-8cbe-525400d85f32 | server1 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
1 row in set (0.00 sec)
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> use test;
Database changed
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
Query OK, 0 rows affected (0.14 sec)
mysql> INSERT INTO t1 VALUES (1, 'Luis');
Query OK, 1 row affected (0.04 sec)
mysql> SELECT * FROM t1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | Luis |
+----+------+
1 row in set (0.00 sec)
[root@server2 ~]# cd /var/lib/mysql
[root@server2 mysql]# ls
auto.cnf ib_logfile0 mysql.sock.lock server2-relay-bin.index
ca-key.pem ib_logfile1 performance_schema server-cert.pem
ca.pem ibtmp1 private_key.pem server-key.pem
client-cert.pem linux public_key.pem sys
client-key.pem master.info relay-log.info
ib_buffer_pool mysql server2-relay-bin.000004
ibdata1 mysql.sock server2-relay-bin.000005
[root@server2 mysql]# systemctl stop mysqld.service
[root@server2 mysql]# rm -fr *
[root@server2 mysql]# systemctl restart mysqld.service
[root@server2 mysql]# grep pass /var/log/mysqld.log
mysql> alter user root@localhost identified by 'Wsp+123ld';
server_id=2
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="15d708f6-b1a7-11e9-9c82-525400d85f32"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "172.25.66.2:33061"
loose-group_replication_group_seeds= "172.25.66.1:33061,172.25.66.2:33061,172.25.66.3:33061"
loose-group_replication_bootstrap_group=off
loose-group_replication_ip_whitelist="127.0.0.1,172.25.66.0/24"
loose-group_replication_enforce_update_everywhere_checks=ON
loose-group_replication_single_primary_mode=OFF
保存退出后,重启服务systemctl restart mysqld
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'Wsp+123ld';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='Wsp+123ld' FOR CHANNEL 'group_replication_recovery';
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
mysql> SET GLOBAL group_replication_allow_local_disjoint_gtids_join=on;
mysql> START GROUP_REPLICATION;
mysql> SHOW PLUGINS;
查看组成员及其状态:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ba729a62-b1c5-11e9-8cbe-525400d85f32 | server1 | 3306 | ONLINE |
| group_replication_applier | cc8f4072-b1c8-11e9-a152-5254000c57b5 | server2 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
如果出现问题,例如MEMBER_STATE
显示RECOVERING
,从以下几点排错:
a.检测所有的MEMBER_ID 是否和master配置文件中loose-group_replication_group_name
不同,才能进行。
b.检查解析文件/etc/hosts
是否配置了和主机名一致的解析。
c.主从库的初始数据可能不一致导致。
这里可以参考博客:
mysql> select * from test.t1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | Luis |
+----+------+
1 row in set (0.00 sec)
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 881fedba-b1ce-11e9-b205-525400aaba12 | server3 | 3306 | ONLINE |
| group_replication_applier | ba729a62-b1c5-11e9-8cbe-525400d85f32 | server1 | 3306 | ONLINE |
| group_replication_applier | cc8f4072-b1c8-11e9-a152-5254000c57b5 | server2 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
mysql> select * from test.t1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | Luis |
+----+------+
1 row in set (0.00 sec)
至此,就完成了组复制(全同步复制)的实验。