失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Mysql进阶(1)——异步复制(主从复制 Gtid复制) 半同步复制

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

时间:2019-12-19 09:13:43

相关推荐

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并写到数据目录的f文件中,官方不建议修改,并且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

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

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进行地址解析

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

5.server1编辑配置文件,开启服务,作为主库

[root@server1 ~]# vim /etc/f[root@server1 ~]# [root@server1 ~]# systemctl start mysqld

在文件末尾写入:

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

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

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

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

7.登陆数据库并授权

[root@server1 ~]# mysql -p

授权

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

注意下图中MASTER进程的相关数据,从库设置中会用到

配置从库

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

[root@server2 ~]# vim /etc/fserver-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就好了

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,表示主库和从库的数据一致

10.回到server1上

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

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

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

[root@server1 mysql]# mysql -pmysql> CREATE DATABASE test;##创建数据库testmysql> USE test;##进入到数据库testmysql> 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;##查看表的所有信息

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

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

数据已同步!!!

二、基于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/f),是一个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/f[root@server1 mysql]# systemctl restart mysqld32 gtid_mode=ON33 enforce-gtid-consistency=true

server2

[root@server2 mysql]# vim /etc/f[root@server2 mysql]# systemctl restart mysqld

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;

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

[root@server1 mysql]# mysql -pmysql> 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> quitBye

写入成功!

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> quitBye[root@server2 mysql]# mysql -pmysql> select * from westos.usertd;

从库数据已经同步!

三、半同步复制

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;##激活插件

(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)

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)

3.查看从库的状态

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

4.查看主库的变量的值,可以查看到延迟时间(10000指10000毫秒,也就是10秒)

mysql> SHOW VARIABLES LIKE '%rpl%';

测试:

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秒之后从库还没有起来,主库不再等待直接写入

等待写入

等待完毕,10秒后直接写入

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

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

这是因为:

半同步复制再一次失败后会自动切换成异步复制

从库进程起来之后会将没有做的事情再做一遍

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

mysql> SHOW STATUS LIKE '%rpl%';

(5)主库查看当前数据

mysql> SELECT * FROM test.redhat;

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

mysql> SELECT * FROM test.redhat;

(7)从库开启io进程

mysql> start slave io_thread;

(8)再次查看数据,数据已同步

也就是说只要从库的io进程恢复工作就会立即同步没有同步的数据

mysql> SELECT * FROM test.redhat;

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

再次验证:

主库添加数据

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> SELECT * FROM test.redhat;

将插件安装在数据库中是临时的,退出重新登陆会失效,永久的可以将配置写在配置文件中

如果觉得《Mysql进阶(1)——异步复制(主从复制 Gtid复制) 半同步复制》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。