day10-02-GTID复制-半同步

GTID *****

TID(Global Transaction ID)是对于一个已提交事务的唯一编号,并且是一个全局(主从复制)唯一的编号。
它的官方定义如下:
GTID = source_id :trans action_id
7E11FA47-31CA-19E1-9E56-C43AA21293967:29
什么是sever_uuid,和Server-id 区别?
核心特性: 全局唯一,具备幂等性

优点:保证事务全局统一

GTID限制:

CREATE TABLE ... SELECT语句限制,不能使用这种sql, sql_slave_skip_counter使用GTID时不支持。如果需要跳过事务,请改用源gtid_executed变量的值

create table ....select statements
case重现:
master:直接执行一个create table select * from table;的sql

报错:
error 1786: Statement violates GTID consistency: CREATE TABLE ... SELECT.

原理:
由于create table ...select语句会生成两个sql,
一个是DDL创建表SQL,
一个是insert into 插入数据的sql。
由于DDL会导致自动提交,所以这个sql至少需要两个GTID,但是GTID模式下,只能给这个sql生成一个GTID,如果强制执行会导致和上面更新非事务引擎一样的结果。
create table xxx as select 的方式会被拆分成两部分。
create table xxxx like data_mgr;
insert into xxxx select * from data_mgr;

GTID核心参数

重要参数

[mysqld]
#GTID:
gtid-mode=on                        #--启用gtid类型,否则就是普通的复制架构
enforce-gtid-consistency=true       #--强制GTID的一致性
log-slave-updates=1  #--强制slave将更新记入日志,5.7.5 版本开始无需在GTID模式下启用参数

#binlog
log-bin=mysql-bin 	#开启二进制文件系统
server-id=1    #必须为 1-231 之间的一个正整数值,各个值节点不能一致



CHANGE MASTER TO
  MASTER_HOST='10.0.50.61',
  MASTER_USER='repl',
  MASTER_PASSWORD='repl',
  MASTER_PORT=3307,
  MASTER_AUTO_POSITION=314;	# 从binlog里position号=1的事务开始读取

# 如果用XBK物理备份文件恢复的话,slave节点是不知道GTID已经包含的事务号范围。一定要看恢复后的binlog最大position号到哪里,然后 MASTER_AUTO_POSITION 设置为 binlog 最大的position号位置
# 例:MASTER_AUTO_POSITION = 100001;

# 或者 可以手工 set gtid purge 指定已经包含的事务范围,然后再恢复
SET @@GLOBAL.GTID_PURGED='7a995d76-0a32-11eb-9c4a-525400c58226:1-50,
b4dfda8a-0f89-11eb-a610-525400c58226:1-7,
de25c9af-0f86-11eb-a80f-525400c58226:1-9';

搭建GTID 主从复制:

清理环境:

root@mysql-node01 data]# systemctl stop mysqld330{7,8,9}
[root@mysql-node01 data]# 
[root@mysql-node01 data]# rm -rf /data/330{7,8,9}/data/*
[root@mysql-node01 data]# rm -rf /data/330{7,8.9}/bin-log/*
[root@mysql-node01 data]# 

准备配置文件

[root@mysql-node01 data]# cat /data/3307/conf/my.cnf 
#服务端配置
[mysqld]

#用户
user=mysql

#软件安装目录
basedir=/application/mysql

#数据目录
datadir=/data/3307/data

#socket文件存放目录
socket=/data/3307/mysql.sock

#Mysql服务器id(1-65535)之间
server_id=3307

#服务端口号
port=3307

#错误日志
log_error=/data/3307/logs/err-mysql.log

#二进制日志
log_bin=/data/3307/bin-log/mysql-bin

#日志记录模式
binlog_format=row

#GTID
gtid-mode = on
enforce-gtid-consistency = true
log-slave-updates = 1

#客户端配置
[mysql]

#socket文件位
socket=/data/3307/mysql.sock

prompt=3307 [\\d]>
[root@mysql-node01 data]#

配置文件复制到slave 节点:

 cp -a my.cnf /data/3308/conf/
 cp -a my.cnf /data/3309/conf/
 
 sed -i 's#3307#3308#g' /data/3308/conf/my.cnf
 sed -i 's#3307#3309#g' /data/3309/conf/my.cnf

初始化数据:

[root@mysql-node01 data]# mysqld --initialize-insecure --user=mysql --basedir=/application/mysql --datadir=/data/3309/data
[root@mysql-node01 data]# mysqld --initialize-insecure --user=mysql --basedir=/application/mysql --datadir=/data/3308/data
[root@mysql-node01 data]# mysqld --initialize-insecure --user=mysql --basedir=/application/mysql --datadir=/data/3307/data
[root@mysql-node01 data]#

启动数据库:

[root@mysql-node01 data]# systemctl start mysqld330{7,8,9}
[root@mysql-node01 data]# 
[root@mysql-node01 data]# ss -lntp|grep 330
LISTEN     0      80        [::]:3307                  [::]:*                   users:(("mysqld",pid=1718,fd=22))
LISTEN     0      80        [::]:3308                  [::]:*                   users:(("mysqld",pid=1720,fd=22))
LISTEN     0      80        [::]:3309                  [::]:*                   users:(("mysqld",pid=1722,fd=22))
[root@mysql-node01 data]# 

构建主从

master : 3307
slave  : 3308, 3309

3307:
grant replication slave on *.* to repl@'10.0.50.%' identified by 'repl';

3308,3309:
CHANGE MASTER TO
  MASTER_HOST='10.0.50.61',
  MASTER_USER='repl',
  MASTER_PASSWORD='repl',
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1;


start slave;

查看状态

mysql> show slave status\G
......
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: b4dfda8a-0f89-11eb-a610-525400c58226:1-5
......
mysql> 

Retrieved_Gtid_Set : 已经接收到的GTID事务
Executed_Gtid_Set: 已经执行的GTID事务

GTID 复制和普通复制搭建时的区别

# 非GTID
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=444,

# GTID:
MASTER_AUTO_POSITION=1;

start slave;

(0)在主从复制环境中,主库发生过的事务,在全局都是由唯一GTID记录的,更方便Failover
(1)额外功能参数(3个)
(2)change master to 的时候不再需要binlog 文件名和position号,MASTER_AUTO_POSITION=1;
(3)在复制过程中,从库不再依赖master.info文件,而是直接读取最后一个relaylog的 GTID号
(4) mysqldump备份时,默认会将备份中包含的事务操作,以以下方式
    SET GLOBAL.GTID_PURGED='2677eeca-1211-11eb-b8be-5254005f3db3:1-8,
3e415a02-11b9-11eb-a650-525400578838:1-4,
7c1e489c-1210-11eb-b591-525400c58226:1-49,
b4dfda8a-0f89-11eb-a610-525400c58226:1-5';
    告诉从库,我的备份中已经有以上事务,你就不用运行了,直接从下一个GTID开始请求binlog就行。

mysqldump --set-gtid-purged=off NONONO


使用 XBK(xtrabackup) 备份 搭建 主从时:

xtrabackup_binlog_info 包含了 GTID 在信息

主节点:

cat xtrabackup_binlog_info
mysql.binlog.000011   489     2478c036-bd7a-11e8-85df-080027206a62:5-6,fbfd9bcb-0437-11e9-947d-080027206a62:1-9

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

从节点:

mysql> reset master; #清除master信息

mysql> set global gtid_purged='2478c036-bd7a-11e8-85df-080027206a62:5-6,fbfd9bcb-0437-11e9-947d-080027206a62:1-9';
# 告诉从库,我的备份中已经有以上事务,你就不用运行了,直接从下一个GTID开始请求binlog就行。

mysql> CHANGE MASTER TO
  MASTER_HOST='10.0.50.61',
  MASTER_USER='repl',
  MASTER_PASSWORD='repl',
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1;

mysql> start slave;
mysql> show slave status\G

错误跳过(不建议使用,最好重新构建主从关系)

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

使用mysqldump备份 搭建主从时:

mysqldump备份的时候需要指定–master-data,默认会将备份中包含的事务操作,以以下方式记录

SET GLOBAL.GTID_PURGED='2677eeca-1211-11eb-b8be-5254005f3db3:1-8,
3e415a02-11b9-11eb-a650-525400578838:1-4,
7c1e489c-1210-11eb-b591-525400c58226:1-49,
b4dfda8a-0f89-11eb-a610-525400c58226:1-5';

# 告诉从库,我的备份中已经有以上事务,你就不用运行了,直接从下一个GTID开始请求binlog就行

在导出的语句中包括:

set @@GLOBAL.GTID_PURGED=’c8d960f1-83ca-11e5-a8eb-000c29ea831c:1-745497′;

#恢复时,需要先在slave上执行一个
reset master;

#再执行
change master to

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


半同步 ***

解决主从复制数据一致性的问题。

master将每个事务写入binlog(sync_binlog=1),传递到slave刷新到磁盘(sync_relay=1),同时主库提交事务(commit)。master等待slave反馈收到relay log,只有收到ACK后master才将commit OK结果反馈给客户端

![这里写图片描述](D:\data\Sync-data\simon\学习笔记\Mysql 笔记\MySql-DBA\MySQL\day10-02-GTID复制-半同步.assets\20180818233027368)

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个slave接收到并且 flush binlog到 Relay Log 文件中才返回给客户端。主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全完成并且提交的反馈

相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间

半同步复制最好在低延时的网络中使用

DUMP_T发送数据给IO_T,DUMP_T会等到IO_T写入relay-log并回复ACK确认,才认为事务是完成的。

缺点:DUMP_T是串行发送,容易阻塞,性能差

ACK,从库relay落地,IO线程会返回一个ACK_reciver。主库事务才能提交。如果主库没有收到ACK_RECIVER确认,超时10秒会切换为异步复制。

官方半同步复制的概念:

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

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

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

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

5.半同步复制的功能要在 Master,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
posted @ 2022-11-24 20:26  oldSimon  阅读(33)  评论(0)    收藏  举报