mysql主从复制和基于gtid的主从、半同步复制

本文详细介绍了MySQL的主从复制原理,包括异步复制、基于GTID的复制和半同步复制。主从复制用于实现数据实时灾备、读写分离和备份。在GTID模式下,无需指定日志文件和位置,通过GTID保证数据完整性。半同步复制确保至少一个从库执行事务后主库才返回。此外,还涉及了基于组提交的并行复制,提高复制效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、了解主从复制

1.主从复制的原理:

影响MySQL-A数据库的操作,在数据库执行后,都会写入本地的日志系统A中。假设,实时的将变化了的日志系统中的数据库事件操作,在MYSQL-A的3306端口,通过网络发给MYSQL-B。MYSQL-B收到后,写入本地日志系统B,然后一条条的将数据库事件在数据库中完成。那么,MYSQL-A的变化,MYSQL-B也会变化,这样就是所谓的MYSQL的复制,即MYSQL replication。

在上面的模型中,MYSQL-A就是主服务器,即master,MYSQL-B就是从服务器,即slave。

日志系统A,其实它是MYSQL的日志类型中的二进制日志,也就是专门用来保存修改数据库表的所有动作,即bin log

日志系统B,并不是二进制日志,由于它是从MYSQL-A的二进制日志复制过来的,并不是自己的数据库变化产生的,有点接力的感觉,称为中继日志,即relay log。

可以发现,通过上面的机制,可以保证MYSQL-A和MYSQL-B的数据库数据一致,但是时间上肯定有延迟,即MYSQL-B的数据是滞后的。

2.主从复制的几种方式:

同步复制

所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。

这样,显然不可取,也不是MYSQL复制的默认设置。比如,在WEB前端页面上,用户增加了条记录,需要等待很长时间

异步复制

如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。

半同步复制

master只保证slaves中的一个操作成功,就返回,其他slave不管。

这个功能,是由google为MYSQL引入的。

3.mysql主从复制用途

1)实时灾备,用于故障切换

2)读写分离,提供查询服务

3)备份,避免影响业务

4.主从部署必要条件:

1)主库开启binlog日志(设置log-bin参数)

2)主从server-id不同

3)从库服务器能连通主库

MySQL复制原理,其通过三个线程来完成,在master节点上运行的binlogdump线程以及在slave节点上运行的I/O线程和SQL线程。
1. master节点上的binlogdump线程,在slave与其正常连接的情况下,将binlog发送到slave上。
2.slave节点上的I/O线程,通过读取master节点发送的内容,并将数据复制到本地的relaylog(中继日志)中。
3.slave节点上的SQL线程,读取relaylog中的日志,并将其事务在本地执行。

二、mysql异步复制

在主节点上执行完命令之后生成一个日志文件,然后将日志文件发送给从节点,最后提交,从节点收到日志文件后,开始同步里面的数据(事物),最后得到与主节点一致的数据
环境:rhel6.5
两台主机:server1:master
server2:slave
1) 在两台主机上安装服务
在server1(master)和server2上(master)

tar xf mysql-5.7.17-1.el6.x86_64.rpm-bundle.tar  ##解压安装包
yum install -y mysql-community-client-5.7.17-1.el6.x86_64.rpm
mysql-community-common-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm
mysql-community-server-5.7.17-1.el6.x86_64.rpm

在server1上(master) 
vim /etc/my.cnf

写入:server-id=1       #数据库中的id号,三者不能相同
log-bin=mysql-bin        #允许slave同步自己的二进制文件

/etc/init.d/mysqld start ###打开数据库
grep password /var/log/mysqld.log ###查看日志,l里面有数据库初始密码

mysql_secure_installation ###进行数据库初始化

mysql -p     

show databases;

mysql> grant replication slave on *.* to westos@’172.25.45.%’ identified by ‘SHIjin_?’; #对172.25.45.%网段有权限同步

show master status     ##查看master的状态

在server2上(slave)
查看授权是否成功
mysql -u westos -p -h 172.25.45.1

vim /etc/my.cnf 写入:server-id=2

/etc/init.d/mysqld start

grep password /var/log/mysqld.log ##查看日志,看初始化密码

mysql_secure_installation ###进行数据库初始化

mysql -p ###登陆即可,密码为你设定的密码

在master中:
mysql> show master status;

在slave中:

change master to master_host='172.25.45.1',master_user='westos',master_password='SHIjin_?',master_log_file='mysql-bin.000004',master_log_pos=1089;          # master_log_file和master_log_pos与上边server1的保持一致

mysql> start slave;

mysql> show slave status\G

这两个参数都为yes就证明成功了
Slave_IO_Running: Yes
Slave_SQL_Running: Yes


测试:
在master中:

mysql> create database test;

mysql> use test;

mysql> create table userlist(    

username varchar(15) not null,    

password varchar(25) not null);    

select * from userlist;

在slave中:

nysqk> usr test;

mysql= select * from userlist;

三、基于gtid模式

1.概念:GTID(Global Transaction Identifier)称为全局事务标示符, 是由mysql服务器自动管理的在原始master上提交事务时被创建。 GTID需要在全局的主-备拓扑结构 中保持唯一性,每一个 GTID 代表一个数据库事务。

GTID由两部分组成: source_id和transaction_id

source_id: 用于表示源服务器,用server_uuid来表示

transaction_id: 则是根据在源服务器上第几个提交的事务来确定。 transaction_id 是一个从 1 开始的自增计数,表示在这个主库上执行的第 n 个事务。 MySQL 会保证事务与 GTID 之间的 1 : 1 映射。

工作原理:前面在slave端配置,进行change master to操作时, 使用的是日志号(指定position),当master端的服务down掉了, 就会在slave端选择一个日志号与原来的master最接 近的作为master, 但是,在另一个slave上,并没有指定新的master的信息, 因此还要手动去指定,而使用gtid的话,slave通过寻找 next的值, 并不用指定master的二进制日志文件和日志号,所以使用gtid更能保证数据的完整性。

1、master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。

2、slave端的i/o 线程将变更的binlog,写入到本地的relay log中。

3、sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。

4、如果有记录,说明该GTID的事务已经执行,slave会忽略。

5、如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。

在master:中

vim /etc/my.cnf
gtid_mode=ON     ##开启gtid模式
enforce-gtid-consistency=true


 /etc/init.d/mysqld restart   ###重启mysql

在slave中:

vim /etc/my.cnf                   ##开启gtid模式

gtid_mode=ON

enforce-gtid-consistency=true

/etc/init.d/mysqld restart

mysql -p

mysql> stop slave;

mysql>change master to master_host='172.25.45.1',master_user='westos',master_password='SHIjin_?',MASTER_AUTO_POSITION=1;

mysql> start slave;

mysql> show slave status\G;

测试
在master中:

mysql> use test;
mysql> show tables;


mysql> delete from userlist where username='user3';

在slave中:

mysql> use test;
mysql> select * from userlist;

####如果出现i/o线程:connection状态。可能原因是执行change命令时密码错误

四、半同步复制配置

(一)master----->slave

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

全同步复制指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

注意:半同步复制模式必须在主服务器和从服务器端同时开启,否则主服务器默认使用异步复制模式。

半同步复制与异步复制的切换:

半同步复制的工作原理就是当slave从库IO_Thread线程将binlog日志接收完毕之后,要给master主库一个确认,如果rpl_semi_sync_master_timeout=10000 (10秒)超过10秒未收到slave从库的接受确认信号,那么就会自动切换为传统的异步复制模式。
在master中:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

mysql> set global rpl_semi_sync_master_enabled=1;

mysql> show variables like '%semi_sync%';


从节点(slave):

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

mysql> set global rpl_semi_sync_slave_enabled=1;

mysql> stop slave io_thread;

mysql> start slave io_thread;

mysql> show global variables like '%semi%';

插入检测:
在master中:

mysql>  use test;
mysql>  insert into userlist values ('user3','123');
mysql>  show status like '%semi_sync%';

Rpl_semi_sync_master_yes_tx ##使用半同步成功的次数,数据一致性性能提高
Rpl_semi_sync_master_no_tx####使用半同步失败的次数,10s后没有得到反馈信息,会转为异步复制

将slave的半同步关掉,进行插入测试:
在slave中:

mysql> set global rpl_semi_sync_slave_enabled=OFF; ###将半同步设置为关闭

mysql> stop slave io_thread;

mysql> start slave io_thread;

mysql> show global variables like '%semi%';

在master中:
当把从机的I/O线程关闭后,主数据库在进行对复制数据库的库进行更改时,在进行操作会等待10秒,10s后没有得到反馈信息,会转为异步复制增加了一次半同步传输的失败次数。
mysql> insert into userlist values ('user4','666');

Query OK, 1 row affected (10.31 sec) #本次插入花费了十秒,因为异步复制有十秒等待slave发送ack的时间.

mysql> show global status like '%semi%';

(二)master---->slave(master)----->slave

实验环境:server1:172.25.45.1和server2连接的master端

                     server2:172.25.45.2相对于server1是slave端相当于server3是master端

                     server3;172.25.45.3和server2连接的slave端

保持上一步中server1master的设置

1.保持server1中上一步的设置 然后对数据库test进行备份并复制到server3中 因为主从复制需要各个端的数据保持一致

mysqldump -p test < test.sql    ##对server1中数据库中操作的数据备份 备份文件为test.sql

此处warning提示备份文件中包含gitd的相关配置信息

scp test.sql root@172.25.45.3:/root     ##将备份数据复制到server3中

2.server2中:

vim /etc/my.cnf

server-id=2
log-bin=mysql-bin
log-slave-updates=ON

gtid_mode=ON
enforce-gtid-consistency=true

slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

/etc/init.d/mysqld restart

mysql -p

grant replication slave on *.* to westos@'%' identified by 'SHIjin;1';   ##给server2master授权

在server3中测试: mysql -h 172.25.45.2 -u westos -p(提前安装好相关包并且开启mysqld服务)

3.sevrer3中执行上个实验中只充当slave的server2一样的操作:

yum install -y mysql-community-client-5.7.17-1.el6.x86_64.rpm
mysql-community-common-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm
mysql-community-server-5.7.17-1.el6.x86_64.rpm

/etc/init.d/mysqld start

vim /etc//my.cnf

/etc/init.d/mysqld restart

然后对进行数据库初始化:

grep password /var/log/mysql.log

mysql_secure_installation(第一个enter其余Y)

mysql -p

show databases;      #此时可以看到server1上的数据库

mysqladmin -p create test          ##在server3中创建和server1一样的数据库名

mysql -p test < test.sql                ##将test.sql中备份的数据导入test中

mysql -p

4.在server2上:

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

show plugins;

set global rpl_semi_sync_master_enabled=1;###重启mysqld服务之后需要重新加此参数或者直接将此参数加如/etc/my.cnf中

show slave status\G;

 5在sevrer3中:

mysql -p;

use mysql;

show tables;

select * from gtid_executed;   ###3表示gtid使用3次

change master to master_host='172.25.45.2',master_user='westos',master_password='SHIjin_?1',master_auto_position=1;

##执行change命令时需要提前关闭slave    : stop slave    操作完成之后需要开启

start slave;

show slave status/G;       

6.在sevrer1中做插入测试:

use test;

insert into userlist values ('user4','123');

在server2中:

show status like '%rpl%'     ##可以看到两个插件都是关闭状态

 set global rpl_semi_sync_master_enabled=1 ;

set global rpl_semi_sync_slave_enabled=1;     ##这两个参数在mysqld服务重启之后都会消失需要重新设定

stop slave io_thread;

start slave io_thread;

show status like '%rpl%'

在server3中安装插件并开启:

INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

 set global rpl_semi_sync_slave_enabled=1;

stop slave io_thread;

start slave io_thread;

server2中重新开启 

set global rpl_semi_sync_master_enabled=1 ;参数

show status like '%rpl%'

插入测试:

在server1中:

insert into userlist values ('user5','123');
在server2中:rpl_semi_sync_master_yes_tx=1表示matser成功连接一次

在server3中:select * from userlist   可以看到数据同步过来了

五.基于组提交的并行复制

并发复制是数据库级别的,这意味着一个SQL线程可以处理一个数据库的连续事务,而不用等待其它数据库完成。这个版本的并发复制,可以理解成一个数据库一个SQL线程

在slave(server2)中:

vim /etc/my.conf

slave-parallel-type=LOGICAL_CLOCK 基于组提交的并行用户
slave-parallel-workers=16         开启16个work:单线程变成多线程(前两个必须加入,后面为优化)
master_info_repository=TABLE      优化选项,默认以文件存储,记录master信息,用表来记录,更新速度更快   
relay_log_info_repository=TABLE  读日志信息,用表来记录(原来是刷在磁盘里)

relay_log_recovery=ON            激活recovery:读取master二进制日志,如果损坏,直接丢弃然后重新读取

mysql -p

use mysql;

show tables;

最终结果:slave进程查看(多个线程在等待主线程的调用)

show peocesslist;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值