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结果反馈给客户端

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个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

浙公网安备 33010602011771号