Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制

前言

原理总结

异步复制:在主节点写入日志即返回成功,默认情况下MySQL5.5/5.6/5.7和mariaDB10.0/10.1的复制功能是异步的。异步复制可以实现最佳的性能,主库把binlog日志发送给从库,这一动作就结束了,并不验证从库,会造成主从库数据不一致。

GTID复制不像传统的复制方式(异步复制、半同步复制)需要找到binlog(MASTER_LOG_FILE)和POS点(MASTER_LOG_POS),只需要知道master的IP、端口、账号、密码即可。因为复制是自动的,MySQL会通过内部机制GTID自动找点同步。
GTID复制名词释义:

  • 1、server-id:服务器身份id,在初始化MySQL时,会自动生成一个server-id并写到数据目录的auto.cnf文件中,官方不建议修改,并且server-id跟GTID有密切关系。
  • 2、GTID:全局事务标识符,使用这个功能时,内次事务提交都会在binlog里生成一个唯一的标识符,它由UUID和事务ID组成,首次提交的事务为1,第二次为2,第三次为3,以此类推
    开启GTID,无需找到binlog和POS点,直接change master to master_auto_postion=1即可,它会自动寻找同步

GTID工作流程:

  • 1、在master上一个事务提交,并写入binlog里。
  • 2、binlog日志发送到slave,slave接收并写入中继日志里,slave读取到这个GTID,并设置gtid_next的值。例如
    set @@session。gtid_next=’=fbd841f9-5590-11e8-b819-000c29e6461e’;
    然后告诉slave接下来的事务必须使用GTID,并写入它自己的binlog里。
  • 3、slave检查并确认这个GTID没有被使用,如果没有被使用,那么开始执行这个事务并写入自己的binlog里
  • 4、由于gtid_next的值不为空,slave不会尝试去生成一个新的gtid而是通过主从同步来获取GTID

半同步复制:一主多从模式下,有一个从节点返回成功,即成功,不必等待多个节点全部返回。

MySQL半同步,MySQL5.5由Google贡献的补丁才开始支持半同步复制(semi Replication)模式,该模式可以确保从服务器接收完主服务器发送的binlog日志文件并写入自己的中继日志(relay log)里,然后会给主服务器一个反馈,告诉对方已经接收到完毕,这时主库线程才返回当前session告知操作完成,当出现超时情况时,源主服务器会暂时切换到异步复制模式,直到至少有一台设置为半同步复制模式的从服务器及时收到信息为止。

主从同步可以同步多个数据库,也可以设置为一个数据库同步,如果设置一个数据库,在从服务器上其他数据可以写操作。
半同步复制模式在主服务器和从服务器同时启用,否则主服务器默认使用异步复制模式。

实验环境:

  • 主库:server1: 172.25.6.1
  • 从库: server2:172.25.6.2

一、MYSQL的主从复制

特别提醒:在数据库中进行操作时,事实上大小写都是通用的,但是作为一个专业人士 ?? ,我们还是使用大写

主从复制的要求:

  • (1)主库开启binlog日志(设置log-bin参数)
  • (2)主从server-id不同
  • (3)从库服务器能连同主库

主从复制的原理:

mysql的主从配置又叫replication,AB复制,基于binlog二进制日志,主数据库必须开启binlog二进制日志才能进行复制。

  • (1) master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
  • (2)从库生成两个线程,一个i/o线程,一个SQL线程,i/o线程去请求主库的binlog,
  • (3) slave将master的binary log events拷贝到它的中继日志(relay log);
  • (4)slave重做中继日志中的事件,将更改应用到自己的数据上。

配置主库

1.下载mysql的安装包,解压

[root@server1 ~]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar 

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第1张图片

2.选择下面五个包安装

[root@server1 ~]# yum install 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 

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第2张图片
3.将server1安装的包传给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 server2:/root   ##如果你写server2的话,需要提前在本机上对server2进行地址解析

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第3张图片

4.server2也安装mysql

[root@server2 ~]# yum install 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 

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第4张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第5张图片
5.server1编辑配置文件,开启服务,作为主库

[root@server1 ~]# vim /etc/my.cnf
[root@server1 ~]# 
[root@server1 ~]# systemctl start mysqld

在这里插入图片描述
在文件末尾写入:
在这里插入图片描述

6.开启服务之后生成了一个临时密码,使用临时密码进行数据库安全初始化

[root@server1 ~]# grep password /var/log/mysqld.log 
[root@server1 ~]# mysql_secure_installation 

在这里插入图片描述
安全初始化登陆的时候使用的是临时密码,接下来要自己设置数据库的密码,这个密码必须有特殊字符,英文字母的大小写还有数字

设置完新密码,第一个选项回车跳过,其他的输入Y就好了
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第6张图片

7.登陆数据库并授权

[root@server1 ~]# mysql -p

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第7张图片
授权

mysql> SHOW DATABASES;
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'172.25.6.%' IDENTIFIED BY 'ZHOUpeng123.';
mysql> SHOW MASTER STATUS;

注意下图中MASTER进程的相关数据,从库设置中会用到
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第8张图片

参数 解释
REPLICATION 表示复制的权限
* .* 表示对所有哭的所有表都授权
repl 用户名
‘172.25.6.%’ 授权172.25.6网段的所有都可以同步

配置从库

8.server2同样编辑配置文件,然后进行安全初始化

[root@server2 ~]# vim /etc/my.cnf
server-id = 2								##文件末写入
[root@server2 ~]# ll /var/lib/mysql			##第一次启动前要保证这个目录里没有数据
total 0
[root@server2 ~]# systemctl start mysqld
[root@server2 ~]# grep password /var/log/mysqld.log 
[root@server2 ~]# mysql_secure_installation 

设置完新密码,第一个选项回车跳过,其他的输入Y就好了

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第9张图片

9.安全初始化完成之后登陆数据库进行授权

[root@server2 ~]# mysql -p
##查看所有的表
mysql> SHOW DATABASES;

##配置主库的信息
mysql> CHANGE MASTER TO MASTER_HOST='172.25.6.1',   ##主库的ip地址
MASTER_USER='repl',                                 ##主库的用户
MASTER_PASSWORD='ZHOUpeng123.',                     ##主库用户的密码
MASTER_LOG_FILE='mysql-bin.000002',                 ##主库的日志文件
MASTER_LOG_POS=690;                                 ##主库的状态码

mysql> 
mysql> START SLAVE;                                 ##开启从库
查看从库状态
mysql> SHOW SLAVE STATUS\G							##可以看到的当前两个进程都是yes,表示主库和从库的数据一致

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第10张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第11张图片

10.回到server1上

查看mysql数据目录下的文件,有刚刚显示的日志文件

[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# ls

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第12张图片

再次登陆数据库,创建数据

[root@server1 mysql]# mysql -p
mysql> CREATE DATABASE test;						##创建数据库test
mysql> USE test;									##进入到数据库test
mysql> SHOW TABLES;									##查看表
mysql> CREATE TABLE redhat (						##创建表redhat
    -> username varchar(10) not null,
    -> password varchar(15) not null);
mysql> DESC redhat;									##查看表的结构
mysql> INSERT INTO usertd VALUES ('user1','123');	##向表中插入信息
mysql> SELECT * FROM usertd;						##查看表的所有信息

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第13张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第14张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第15张图片

11.server2查看,数据是否同步

mysql> SHOW DATABASES;				##查看所有数据库,可以看到现在有一个test数据库
mysql> USE test;					##进入到test数据库的环境
mysql> SELECT * FROM redhat;		##查看redhat表的所有信息
mysql> quit							##退出

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第16张图片

数据已同步!!!
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第17张图片

二、基于gtib的主从复制

  • GTID即全局事务ID (global transaction identifier), 其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID。GTID最初由google实现,官方MySQL在5.6才加入该功能。mysql主从结构在一主一从情况下对于GTID来说就没有优势了,而对于2台主以上的结构优势异常明显,可以在数据不丢失的情况下切换新主。

  • GTID实际上是由UUID+TID (即transactionId)组成的。其中UUID(即server_uuid) 产生于auto.conf文件(cat /data/mysql/data/auto.cnf),是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增,所以GTID能够保证每个MySQL实例事务的执行(不会重复执行同一个事务,并且会补全没有执行的事务)。

  • GTID在一组复制中,全局唯一。通过GDIT保证每个主库上提交的事务在集群中有一个唯一的ID.这种方式强化了数据库的主备一致性,故障恢复以及容错能力。

  • 主从复制,默认是通过pos复制(postion),就是说在日志文档里,将用户进行的每一项操作都进行编号(pos),每一个event都有一个起始编号,一个终止编号,我们在配置主从复制时从节点时,要输入master的log_pos值就是这个原因,要求它从哪个pos开始同步数据库里的数据,这也是传统复制技术。

  • pos和GTID都是日志文件里事件的一个标志,如果将整个mysql集群看作一个整体,pos就是局部的,GTID就是全局的.

配置过程:

1.主从库都编辑配置文件,重启mysqld服务

server1

[root@server1 mysql]# vim /etc/my.cnf
[root@server1 mysql]# systemctl restart mysqld

 32 gtid_mode=ON
 33 enforce-gtid-consistency=true

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第18张图片
server2

[root@server2 mysql]# vim /etc/my.cnf
[root@server2 mysql]# systemctl restart mysqld

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第19张图片

2.server2登陆数据库

[root@server2 mysql]# mysql -p			##查看从库的状态
mysql> SHOW SLAVE STATUS\G				##切换到mysql数据库
mysql> USE mysql;						##查看表,有一个gtid_executed表
mysql> SHOW TABLES;						##查看标准表中的所有数据
mysql> SELECT * FROM gtid_executed;

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第20张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第21张图片
在这里插入图片描述

3.回到server1上,登陆数据库

[root@server1 mysql]# mysql -p			
mysql> USE test										##切换到test库
mysql> INSERT INTO redhat VALUES ('user2','123');	##向redhat表中插入数据
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO redhat VALUES ('user3','123');	
Query OK, 1 row affected (0.00 sec)
mysql> select * from redhat;						##查看数据
mysql> quit
Bye

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第22张图片
写入成功!
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第23张图片

4.在server2从库上查看新写入的数据是否同步

mysql> SHOW SLAVE STATUS\G								##查看从库状态				
mysql> SELECT * FROM gtid_executed;						##查看gtid_executed表中的数据,可以看到在主库中做的操作被记录

mysql> STOP SLAVE;										##停止从库

mysql> CHANGE MASTER TO MASTER_HOST='172.25.19.1',MASTER_USER='repl',
MASTER_PASSWORD='Yjy+123+mm',MASTER_AUTO_POSITION=1;
##改变主库的信息,从1开始记录

mysql> START SLAVE;										##开启从库

mysql> SHOW SLAVE STATUS\G								##查看状态,数据一致,从1开始记录

mysql> quit
Bye
[root@server2 mysql]# mysql -p
mysql> select * from westos.usertd;

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第24张图片
在这里插入图片描述
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第25张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第26张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第27张图片
从库数据已经同步!
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第28张图片

三、半同步复制

  • MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
    半同步复制就是为了解决数据丢失的问题。

1.主从库都安装插件

(1)master(主库)

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
##可以查看到插件已经安装

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
    -> FROM INFORMATION_SCHEMA.PLUGINS
    -> WHERE PLUGIN_NAME LIKE '%semi%';

mysql> SET GLOBAL rpl_semi_sync_master_enabled=1;			##激活插件

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第29张图片
(2)slave端(从库)

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进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第30张图片

2.从库重启io进程,激活插件之后必须要重启io进程,否则不会生效,如果重启不了的话就说明两端的数据不同步

mysql> stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第31张图片

3.查看从库的状态

mysql> SHOW SLAVE STATUS\G
mysql> SHOW STATUS LIKE '%rpl%';					##查看变量状态
mysql> SHOW VARIABLES LIKE '%rpl%';					##查看变量的值

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第32张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第33张图片
4.查看主库的变量的值,可以查看到延迟时间(10000指10000毫秒,也就是10秒)

mysql> SHOW VARIABLES LIKE '%rpl%';

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第34张图片

测试:

1.serve2先关闭io进程

mysql> stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)

2.server1写入数据

(1)进入test库

mysql> USE test;

(2)插入数据到redhat表

mysql> INSERT INTO redhat VALUES ('user4','123');
Quy OK, 1 row affected (10.01 sec)

有10秒的延迟,这是因为从库的io进程关闭了,不能及时的写入数据;主库等待10秒之后从库还没有起来,主库不再等待直接写入

等待写入
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第35张图片
等待完毕,10秒后直接写入
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第36张图片

(3)再次插入数据,主库直接写入,没有延迟

mysql> INSERT INTO redhat VALUES ('user5','123');
Query OK, 1 row affected (0.00 sec)

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第37张图片

这是因为:
半同步复制再一次失败后会自动切换成异步复制
从库进程起来之后会将没有做的事情再做一遍

(4)查看主库的变量,半同步复制关闭

mysql> SHOW STATUS LIKE '%rpl%';

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第38张图片

(5)主库查看当前数据

mysql> SELECT * FROM test.redhat;

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第39张图片

(6)从库查看当前数据,没有刚刚主库写入的数据——数据未同步

mysql> SELECT * FROM test.redhat;

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第40张图片

(7)从库开启io进程

mysql> start slave io_thread;

(8)再次查看数据,数据已同步
也就是说只要从库的io进程恢复工作就会立即同步没有同步的数据

mysql> SELECT * FROM test.redhat;

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第41张图片

总结:半同步复制失败后会自动切换成异步复制,从库进程起来之后会检测主从库数据是否同步;若不同步,将会采用异步复制的方式同步数据

再次验证:
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第42张图片

主库添加数据

mysql> INSERT INTO redhat VALUES ('user6','123');
Query OK, 1 row affected (0.00 sec)

mysql> SHOW STATUS LIKE '%rpl%';
##Rpl_semi_sync_master_yes_tx变成1,成功了1次
主库查看
mysql> SELECT * FROM test.redhat;

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第43张图片
Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第44张图片

从库查看

mysql> SELECT * FROM test.redhat;

Mysql进阶(1)——异步复制(主从复制、Gtid复制)、半同步复制_第45张图片
将插件安装在数据库中是临时的,退出重新登陆会失效,永久的可以将配置写在配置文件中

你可能感兴趣的:(运维企业部分)