• 全世界谁倾听你
  • 网站正式加入腾讯404公益
  • 霸气的藏獒
  • Apache为什么二级域名不能加载证书呢?
  • 将网站做了一个微信小程序了,等待审核!
  • 一张图完美讲述VIM命令
  • 生活中不简简单单是做对的事,更是要把对的事情做对,如果还有一层,那么应该尝试把错的事情也做对! by 尼古拉斯·拉布拉卡
  • 123木头人
  • Windows命令提示符中统计行数
  • 一张图看懂上海17区县名字来源

MySQL主从复制与GTID复制原理

MYSQL IT敢客 3周前 (05-04) 36687次浏览 已收录 0个评论 扫描二维码

        MySQL 主从复制原理阐述

MySQL 复制在业界里有叫:MySQL 同步,AB 复制等。专业名称就是叫:主从复制;复制是单向的,只能从 Master 复制到 Slave 上,延时基本上是毫秒级别的。一组复制结构中可以有多个 Slave,对于 Master 一般场景推荐只有一个

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

三个线程来实现:主库 Binlog Dump,从库 IO 和 SQL 线程

Master 所有数据库变更写进 Binary log, 主库线程 binlog dump 把 Binary log 内容发送到从库 slave 上(slave 被动接受数据,不是主动去获取)。

Slave IO 线程读取 Master 上 Binary log 日志信息,把接受到的 Binary log 日志写到本地中继日志 Relay log

Slave SQL 线程读取 Ralay log 日志内容写入本地数据库实例

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

一、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

二、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

三、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。

四、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。

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

优势

1、更简单的实现 failover,不用以前那样在需要找 log_file 和 log_Pos。

2、更简单的搭建主从复制。

3、复制集群有一个统一的方式识别复制位置,给集群管理带来了便利。

4、正常情况下,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 的工作原理:

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。

6、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

        pos 与 GTID 有什么区别?

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

MySQL 主从复制与 GTID 复制原理 

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

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

为什么要有这个区分呢? 

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

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

MySQL 主从复制与 GTID 复制原理

如果使用的是 pos,三者的 pos 不一致,slave2 怎么去获取它当前要同步的事件在 slave1 里的 pos 呢,很难. 

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

经典主从配置

核心配置 my.cnf

[mysqld]
log-bin
server-id
gtid_mode=off #禁掉 gtid
grant replication slave on *.* to 'repl'@'%' identified by 'repl4slave';
flush privileges;

 

级别

优点

缺点

statement

binlog 文件较小

日志是包含用户执行的原始SQL,方便统计和审计

出现最早,兼容较好

存在安全隐患,可能导致主从不一致

对一些系统函数不能准确复制或是不能复制

row

相比statement更加安全的复制格式

在某些情况下复制速度更快(SQL复杂,表有主键)

系统的特殊函数也可以复制

更少的锁

更新和删除语句检查是否有主键,如果有则直接执行,如果没有,看是否有二级索引,如再没有,则全表扫描

binlog 比较大(myql5.6 支持 binlog_row_image)

单语句更新(删除)表的行数过多,会形成大量 binlog

无法从 binlog 看见用户执行 SQL(5.6 中增加 binlog_row_query_log_events 记录用户的 query)

mixed

混合使用 row 和 statement 格式,对于 DDL 记录 statument,对于 table 里的行操作记录为 row 格式。

如果使用 innodb 表,事务级别使用了 READ_COMMITTED or READ_UMCOMMITTED 日志级别只能使用 row 格式。

但是使用ROW格式中DDL语句还是会记录成statement格式。

mixed 模式中,那么在以下几种情况下自动将 binlog 模式由 SBR 模式改成 RBR 模式。

DML语句更新一个NDB

当函数中包含UUID

2 个及以上 auto_increment 字段的表被更新时

行任何insert delayed语句时

UDF

视图中必须要求使用RBR时,例如创建视图使用了UUID()函数

添加一个新的从库

获取主库上一个带 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;#重启 io 线程,刷新状态
mysql> stop slave io_thread;
mysql> start slave io_thread;

master_host master_user master_password 与主从复制一致, 
唯一不一致的是使用了 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 添加从库:

mysqldump

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

导出的语句中包括:set @@GLOBAL.GTID_PURGED='c8d960f1-83ca-11e5-a8eb-000c29ea831c:1-745497';恢复时,需要先在slave上执行一个reset master;再执行change master to

 

percona xtrabackup

xtrabackup_binlog_info 包含了 GTID 在信息

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

set@@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;

rpel

change master

error

classic

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;

stop slave;

set global sql_slave_skip_counter=1;

start slave;

show slave status\G;

GTID

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 复制默认是异步复制,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 都告知已收到,且它只是接收,并不用等其完全执行且提交。

 

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

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

半同步配置,在masterslave上都配置

master
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000     #1s
 
slave
[mysqld]
rpl_semi_sync_slave_enabled=1 复制参数

master

slave

log-bin=/data/mysql/mysql3316/logs/mysql-bin

server-id=[ip]port

log-bin-index=mysql-bin.index

binlog_format=row

binlog_cache_size=1M

max_binlog_size=1G

sync_binlog=0

expire_logs_days=7

log_bin_trust_function_creators=1 #使用存储过程或函数打开

 

enforce-gtid-consistency=1

gtid-mode=on

gtid-next

gtid-purged

gtid-execued

执行过的 gtid

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

复制过滤

建议能不用就不用,如果必须用,在从库上操作,不要在主库上设置

 

====================

binlog-do-db

binlog-ignore-db

server-id

log_slave_updates

#会把复制的 binlog 也写到 binlog 中

relay_log_recover=1

#在 slave 崩溃或正常启动时,未应用完的 relay_log 会被删掉,重新从 master 请求 binlog 再次生成 relay_log

skip-slave-start

slave_transaction_retries

#slave 复制中,如果因为 innodb 死锁或者锁超时导致复制线程执行的事务失败重试次数,一般为 5

slave_parallel_workers

#5.6 引入基于库计并发复制的功能,默认是关闭的

read-only

#打开只读,但对有 super 权限的用户无效

slave_net_timeout = 10#默认 3600s

slave_skip_errors

 

log-slow-slave-statements

#默认复制慢语句不会记录到慢日志中,启动此功能,会把复制中超过 long_query_time 的语句记录到慢日志中

max_relay_log_size

设置 relay_log 的最大大小,建议不设置

relay-log-info-file

#relay_log 的索引文件

relay_log_purge

默认开启,在 relay_log 使用完毕后,尽可能的清理掉

replicate-same-server-id

对于相同的 server-id 的 binlog event 默认不执行

slave_load_tmpdir

对于复制 load data in file 语句,slave 指定创建临时文件的目录,默认是 tmpdir

relay_log_space_limit

限制 relay_log 战胜磁盘的总大小

 

===========================

#slave to filter

replicate-do-db

replicate-ignore-db

repicate-rewrite-db

如果 master 和 slave 有个库同名了,可使用 rewrite 规则,将这个库上的复制重写到另一个新的库上

replicate-do-table

replicate-ignore-table

replicate-wild-do-table

replicate-wild-ignore-table

参考文档:
https://blog.csdn.net/thundermeng/article/details/50401150 
https://blog.csdn.net/qwq_qaq/article/details/73518795 
https://www.2cto.com/database/201802/720724.html 


IT 敢客 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:MySQL 主从复制与 GTID 复制原理
喜欢 (6556)
[313176056@qq.com]
分享 (0)
IT敢客
关于作者:
“我所做的一切都是为了方便我的生活~~~“
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址