MySQL主从复制-GTID原理

一、MySQL 主从复制原理阐述

Mysql主从复制:简单来说就是Mysql 同步,Ab 复制等,主从复制是单向的,只能从 Master 复制到 Slave 上,延时基本上是毫秒级别的(排除网络延迟等问题)。一组复制结构中可以有多个Slave,对于 Master一般场景推荐只有一个,【根据您的业务进行调配,主主复制、延迟复制等】

Mysql 传统复制是基于 Mysql 二进制文件(Mysql-Bin.000001),加上对应日志文件中每个事件的偏移量位置点(Postion)。

MySQL主从复制 三个线程来实现:

主库: Binlog Dump
从库: IoSql 线程

Mysql同步原理简述:

  1. Master 所有数据库变更写进 Binary Log, 主库线程 Binlog Dump 把 Binary Log 内容发送到从库 Slave 上(Slave 被动接受数据,不是主动去获取)。
  2. Slave Io 线程读取 Master 上 Binary Log 日志信息,把接受到的 Binary Log 日志写到本地中继日志 Relay Log
  3. Slave Sql 线程读取 Ralay Log 日志内容写入本地数据库实例

二、MySQL 异步复制架构中 GTID 复制的原理阐述

2.1 GTID 的概述:

1、全局事物标识:global transaction identifieds。

2、GTID 事物是全局唯一性的,且一个事务对应一个 GTID

3、一个 GTID 在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。

4、GTID 用来代替classic的复制方法,不在使用 binlog+pos 开启复制。而是使用 master_auto_postion=1 的方式自动匹配 GTID 断点进行复制

5、MySQL-5.6.5 开始支持的,MySQL-5.6.10 后开始完善。

6、在传统的 slave 端,binlog 是不用开启的,但是在 GTID 中,slave 端的 binlog 是必须开启的,目的是记录执行过的 GTID(强制);但是从 5.7.5 版本开始无需在 GTID 模式下启用参数 log_slave_updates

2.2 GTID 的组成部分:

  • GTID = source_id:transaction_id
  • source_id 正常即是 server_uuid,在第一次启动时生成(函数 generate_server_uuid),并持久化到 DATADIR/auto.cnf 文件里。
  • transaction_id 是顺序化的序列号(sequence number),在每台 MySQL 服务器上都是从 1 开始自增长的序列,是事务的唯一标识。例如:3E11FA47-71CA-11E1-9E33-C80AA9429562:23
  • GTID 的集合(GTIDs)可以用 source_id+transaction_id 范围表示,例如:3E11FA47-71CA-11E1-9E33-C80AA9429562:1-18
  • 复杂一点的:如果这组 GTIDs 来自不同的 source_id,各组 source_id 之间用逗号分隔;如果事务序号有多个范围区间,各组范围之间用冒号分隔,例如:3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5:11-18,2C256447-3F0D-431B-9A12-575BB20C1507:1-27

2.3 GTID 如何产生

  • GTID 的生成受 gtid_next 控制。
  • 在 Master 上,gtid_next 是默认的 AUTOMATIC,即 GTID 在每次事务提交时自动生成。它从当前已执行的 GTID 集合(即 gtid_executed)中,找一个大于 0 的未使用的最小值作为下个事务 GTID。同时将 GTID 写入到 binlog(set gtid_next 记录),在实际的更新事务记录之前。
  • 在 Slave 上,从 binlog 先读取到主库的 GTID(即 set gtid_next 记录),而后执行的事务采用该 GTID。

2.4 GTID 相关的变量

GTID_EXECUTED

#表示已经在该实例上执行过的事务; 执行 RESET MASTER 会将该变量置空; 我们还可以通过设置 GTID_NEXT 在执行一个空事务,来影响 GTID_EXECUTED

GTID_PURGED

#已经被删除了 binlog 的事务,它是 GTID_EXECUTED 的子集,只有在 GTID_EXECUTED 为空时才能设置该变量,修改 GTID_PURGED 会同时更新 GTID_EXECUTED 和 GTID_PURGED 的值。

GTID_OWNED

#表示正在执行的事务的 gtid 以及对应的线程 ID。

GTID_NEXT

#SESSION 级别变量,表示下一个将被使用的 GTID。

2.5 GTID 比传统复制的优势与限制:

GTID优势

更简单的实现 failover,不用以前那样在需要找 log_file 和 log_Pos。
更简单的搭建主从复制。
复制集群有一个统一的方式识别复制位置,给集群管理带来了便利。
正常情况下,GTID 是连续没有空洞的,因此主从库出现数据冲突时,可以用添加空事物的方式进行跳过。

GTID的限制:

1、在一个事务里面混合使用引擎,如 Innodb(支持事务)、MyISAM(不支持事务), 造成多个 GTIDs 和同一个事务相关联出错
2、CREATE TABLE…..SELECT 不能使用,该语句产生的两个 event 在某一情况 会使用同一个 GTID(同一个 GTID 在 slave 只能被使用一次)
       1th event:创建表语句 create table
       2th event:插入数据语句 insert
3、CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE 不能在事务内使用 (启用了–enforce-gtid-consistency 参数)。

三、GTID 的工作原理:

master 更新数据时,会在事务前产生 GTID,`一同记录到 binlog 日志中`。
slave 端的 i/o 线程将变更的 binlog,写入到本地的 relay log 中,读取值是根据`gitd_next变量`,告诉我们slave下一个执行哪个GTID。
sql 线程从 relay log 中获取 GTID,然后对比 slave 端的 binlog 是否有记录。
如果有记录,说明该 GTID 的事务已经执行,slave 会忽略。
如果没有记录,slave 就会从 relay log 中执行该 GTID 的事务,并记录到 binlog。
在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有二级索引就用全部扫描。

3.1 pos 与 GTID 有什么区别?

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

上图就是一个 mysql 节点的集群,一主两从,在 master,slave1,slave2 日志文件里的 pos,都各不相同,就是一个 event,在 master 的日志里,pos 可能是 700,而在 slave1,slave2 里,pos 可能就是 300,400 了,因为众多 slave 也可能不是同时加入集群的,不是从同一个位置进行同步.

而 GTID,在 master,slave1,slave2 各自的日志文件里,同一个 event 的 GTID 值都是一样的.

3.2 为什么要有这个区分呢?

大家都知道,这整个集群架构的节点,通常情况下,是 master 在工作,其他两个结点做备份,而且,各个节点的机器,性能不可能完全一致,所以,在做备份时,备份的速度就不一样,当 master 突然宕掉之后,马上会启用从节点机器,接管 master 的工作,当有多个从节点时,选择备份日志文件最接近 master 的那个节点;

现在就出现情况了,当 salve1 变成主节点,那slave2就应该从 slave1 去获取日志文件,进行同步.

大家来想想这个问题
如果使用的是pos,三者的pos不一致,slave2 怎么去获取它当前要同步的事件在 slave1 里的 pos 呢?????????

所以就有了GTID全局的,将所有节点对于同一个 event 的标记完全一致,当 master 宕掉之后,slave2 根据同一个 GTID 直接去读取 slave1 的日志文件,继续同步.

四、MySQL经典主从配置实战

4.1 核心配置 my.cnf

[mysqld]
log-bin
server-id
gtid_mode=off #禁掉 gtid

4.2 添加主从复制用户

grant replication slave on *.* to ‘repl‘@‘%‘ identified by ‘qiuyuetao‘;
flush privileges;

4.3 添加一个新的从库

获取主库上一个带 binlog 及 pos 偏移量的备份

在从库上恢复后

>change master to
master_host=‘192.168.199.117‘,
master_user=‘slave‘,
master_port=7000,
master_password=‘slavepass‘,
master_log_file=‘mysql-bin.000008‘,
master_log_pos=896;

>start slave;
>show slave status\G;

跳过复制错误

stop slave;
set global sql_slave_skip_counter=1;
start slave;
show slave status\G;

如果出现错误代码,那么一般错误,可以跳过,具体哪些错误代码可以跳,哪些不能调,后续我会在专门写一篇文章。

五、GTID 配置

所有节点上都要进行设置
vim /etc/my.cnf

[mysqld]
#GTID:
gtid_mode=on    #开启 GTID
enforce-gtid-consistency=on
#binlog
log-bin=mysql-bin   #开启二进制文件系统
server-id=1    #必须为 1-231 之间的一个正整数值,各个值节点不能一致
log-slave-updates=1      # 5.7.5 版本开始无需在 GTID 模式下启用参数 log_slave_updates

在从节点上 mysql 设置:

mysql>change master to master_host=‘xxxxxxx‘,master_user=‘xxxxxx‘,master_password=‘xxxxx‘,MASTER_AUTO_POSITION=1;
mysql> start slave;
mysql> stop slave io_thread; #重启 io 线程,刷新状态
mysql> start slave io_thread;

注意事项:

master_host,master_user,master_password与经典的Mysql主从复制一致。
唯一不一致的是使用了 MASTER_AUTO_POSITION 参数
当使用 MASTER_AUTO_POSITION 参数的时候,MASTER_LOG_FILE,MASTER_LOG_POS 参数不能使用
如果想要从 GTID 配置回 pos,再次执行这条语句,不过把 MASTER_AUTO_POSITION 置为 0

GTID添加从库有两种方法:

1.如果 master 所有的 binlog 还在,安装 slave 后,直接 change master 到 master

原理: 直接获取 master 所有的 gtid 并执行
优点: 简单
缺点: 如果 binlog 太多,数据完全同步需要的时间较长,并且需要 master 一开始就启用了 GTID
总结:适用于 master 也是新建不久的情况

2.通过 master 或者其它 slave 的备份搭建新的 slave.

原理:获取 master 的数据和这些数据对应的 GTID 范围,然后通过在 slave 设置@@GLOBAL.GTID_PURGED 从而跳过备份包含的 GTID
优点: 可以避免第一种方法中的不足
缺点: 操作相对复杂
总结:适用于拥有较大数据集的情况

GTID 添加从库:

1、mysqldump

在备份的时候需要指定–master-data

导出的语句中包括:

set @@GLOBAL.GTID_PURGED=’c8d960f1-83ca-11e5-a8eb-000c29ea831c:1-745497′;
#恢复时,需要先在slave上执行一个
reset master;
#再执行
change master to

2、percona xtrabackup

xtrabackup_binlog_info 包含了 GTID 在信息

做从库恢复后,需要手工设置:

[email protected]@GLOBAL.GTID_PURGED=‘c8d960f1-83ca-11e5-a8eb-000c29ea831c:1-745497‘;

恢复后,执行 change master to

>change master to
master_host=‘192.168.199.117‘,
master_user=‘slave‘,
master_port=7000,
master_password=‘slavepass‘,
master_auto_position=1;

错误跳过

stop slave;
set gtid_next=‘xxxxxxxx:N‘;
begin;
commit;
set gtid_next=‘automatic‘;
start slave;

GTID的限制总结:
不支持非事务引擎(从库报错,stop slave; start slave; 忽略)
不支持 create table … select 语句复制(主库直接报错)
不允许在一个 SQL 同时更新一个事务引擎和非事务引擎的表
在一个复制组中,必须要求统一开启CTID或是关闭GTID
开启DTID需要重启(5.7中可能不需要)
开启DTID后,就不在使用原来的传统的复制方式
对于create temporary table 和drop temporary table语句不支持
不支持sql_slave_skip_counter

六、MySQL半同步复制

MySQL 复制默认是异步复制,Master 将事件写入 binlog,但并不知道 Slave 是否或何时已经接收且已处理。在异步复制的机制的情况下,如果 Master 宕机,事务在 Master 上已提交,但很可能这些事务没有传到任何的 Slave 上。假设有 Master->Salve 故障转移的机制,此时 Slave 也可能会丢失事务

官方半同步复制的概念:

1.当 Slave 主机连接到 Master 时,能够查看其是否处于半同步复制的机制。

2.当 Master 上开启半同步复制的功能时,至少应该有一个 Slave 开启其功能。此时,一个线程在 Master 上提交事务将受到阻塞,直到得知一个已开启半同步复制功能的 Slave 已收到此事务的所有事件,或等待超时。

3.当一个事务的事件都已写入其 relay-log 中且已刷新到磁盘上,Slave 才会告知已收到。

4.如果等待超时,也就是 Master 没被告知已收到,此时 Master 会自动转换为异步复制的机制。当至少一个半同步的 Slave 赶上了,Master 与其 Slave 自动转换为半同步复制的机制。

5.半同步复制的功能要在 Master,Slave 都开启,半同步复制才会起作用;否则,只开启一边,它依然为异步复制。

同步(社区增强半同步),异步,半同步复制的比较:

同步复制:Master 提交事务,直到事务在所有的 Slave 都已提交,此时才会返回客户端,事务执行完毕。缺点:完成一个事务可能会有很大的延迟

异步复制:当 Slave 准备好才会向 Master 请求 binlog。
缺点:不能保证一些事件都能够被所有的 Slave 所接收。

半同步复制:半同步复制工作的机制处于同步和异步之间,Master 的事务提交阻塞,只要一个 Slave 已收到该事务的事件且已记录。它不会等待所有的 Slave 都告知已收到,且它只是接收,并不用等其完全执行且提交。

解决主库不关心日志是否被从库读到

半同步,开启后严重影响性能

半同步配置,在master和slave上都配置

master
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000     #1s

slave
[mysqld]
rpl_semi_sync_slave_enabled=1 复制参数

原文地址:http://blog.51cto.com/qiuyt/2335664

时间: 2024-10-07 02:09:53

MySQL主从复制-GTID原理的相关文章

MySQL主从复制的原理及配置

[http://www.jb51.net/article/50053.htm] MySQL 数据库的高可用性架构: 集群,读写分离,主备.而后面两种都是通过复制来实现的.下面将简单介绍复制的原理及配置,以及一些常见的问题. [优点] 1. 如果主服务器出现问题, 可以快速切换到从服务器提供的服务2. 可以在从服务器上执行查询操作, 降低主服务器的访问压力3. 可以在从服务器上执行备份, 以避免备份期间影响主服务器的服务注意一般只有更新不频繁的数据或者对实时性要求不高的数据可以通过从服务器查询, 

MySQL 主从复制及原理

1.主从复制配置a. 环境:CentOS7.4,IP地址分别是主库:192.168.11.146,从库:192.168.11.238,主库版本应低于或等于从库版本,这里用的都是MySQL 8.0.13b.主库配置/etc/my.cnf文件 [mysqld] #一般配置选项user=mysqlport=3306server_id=1basedir= /usr/local/mysqldatadir= /usr/app/mysqldata character_set_server=utf8 pid_f

MySQL主从复制的原理及配置方法(比较详细)

MySQL 的数据库的高可用性的架构大概有以下几种:集群,读写分离,主备.而后面两种都是通过复制来实现的.下面将简单介绍复制的原理及配置,以及一些常见的问题 一.复制的原理 MySQL 复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新.删除等等).每个从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的更新,以便从服务器可以对其数据拷贝执行相同的更新. 将主服务器的数据拷贝到从服务器的一个途径是使用LOAD DATA FROM MASTER语句.请注意LOAD DATA FRO

Mysql 主从复制GTID

-------------------------------------------- 安装准备 配置/etc/my.cnf 主master grant 分配复制帐号 从slave  change :开启slave:查看状态: 验证一致性 -------------------------------------------- 当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中. binlog传输到slave,并存储到slave的relaylog后,读取这个GTID值设

MySQL主从复制的常见拓扑、原理分析以及如何提高主从复制的效率总结

一.主从复制搭建方法参考 1.MySQL5.6 数据库主从(Master/Slave)同步安装与配置详解请参考: http://blog.csdn.net/xlgen157387/article/details/51331244#comments 2.使用mysqlreplicate命令快速搭建 Mysql 主从复制: http://blog.csdn.net/xlgen157387/article/details/52452394 二.Mysql 主从复制的常用拓扑结构 2.1.一主一从 是最

mysql主从复制与读写分离

MySQL主从复制与读写分离 MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面. 因此,一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力 这样的方案来进行部

MySQL主从复制与读写分离的实现

MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面. 因此,一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力 这样的方案来进行部署与实施的. 如下图所示: 下

MySQL主从复制与读写分离 --非原创

原文出处:http://www.cnblogs.com/luckcs/articles/2543607.html MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面. 因此,一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再

MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践

Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面. 因此,一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力 这样的方案来进行部署与实施的. 如下图所示: 下面是我在实际工作过程中所整理的笔记,在此分享出来,以供大家参考. 一.MySQL的安装与