MySQL GTIDS概述
从MYSQL5.6 开始,mysql开始支持GTID复制。
基于日志点复制的缺点:
从那个二进制日志的偏移量进行增量同步,如果指定错误会造成遗漏或者重复,导致数据不一致。
基于GTID复制:
1.从服务器会告诉主服务器已执行的事务的GTID值。
2.主库会告诉从库哪些GTID事务没有被执行。
同一个事务在指定的从库执行一次。
什么是GTID
GTID即全局事务ID,机器保证为每一个在主库上提交的事务在复制集群中可以生成一个唯一的ID.
GTID=source_id:transaction_id
source_id:是主库的server UUID,在数据目录的auto.cnf 文件中。
transaction_id: 从1开始的一个序列。
通过GTIDs【global transaction identifiers】,可以标识每一个事务,并且可以在其一旦提交追踪并应用于任何一个Slave上;这样 就不需要像BinaryLog复制依赖Log file 和位置。GTIDs完全基于事务,只要在Master提交的所有事务都在Slave上进行了Commit,那么就能保证Master和Slave之间的数据 一致性。你可以使用基于SBR或RBR的GTIDs来实现。推荐使用RBR【Row-based replication】.
1 GTID介绍
GTID的惟一性,不仅仅在Master上惟一,而是在整个集群中惟一。
GTID是由SourceId:transaction_Id 构成;SourceId用于标识源Server,即Master中的server_uuid[系统变量];transaction_id,是按照事务提交顺序而生成的序列数字。如第一个被提交的是1,则其GTID=XXXXXXXXXXXX:1.
GTID被存储于mysql.gtid_executed中,当gtid_mode=ON/ON_PERMISSIVE时。
GTID的生命周期
a.事务在Master上执行并提交
该事务用GTID标识,GTID由Master的UUID和一个非0的未被使用的事务序列号构成;该GTID被写入Master的BinLog中。
b.之后BinLog被传送到Slave上并存储在Slave的relay Log中【using established mechanisms for this process】.Slave读取到这个GTID,并为系统变量gtid_next赋值,这就告诉了Slave下一个要执行的事务【transaction】就是这个。
c.Slave确认该GTID是否已被使用【在其BinLog中】。若未用,则执行transaction并写入BinLog。需要注意的是:不仅仅是检查BinLog而且要确认没有其他session 已读取但未提交。换句话说,多个Clients不允许并行执行同一事务。
d.由于gtid_next不为空。Slave执行并写入BinLog。
2.构建GTID复制
a. 同步数据。即将Master与Slave的数据同步到一致,然后都开启SET @@global.read_only=ON;
b.停止Servers。可使用:mysqladmin -uroot -p shutdown
c.配置主从Server.确保双方都开启gtid_mode=ON,enforce_gtid_consistency=ON。
d.将Slave挂载到Master,告诉Slave将使用哪个Master作为复制的数据源。使用CHANGE MASTER TO语句,一定要启用MASTER_AUTO_POSITION=1,告诉Slave事务将由GTIDS标识。
e.启动Slave. START SLAVE.
f.关闭 read_only. read_only=off;
3.使用GTIDs限制
GTIDs是基于事务的【transactions】,所以对非事务的操作不会支持。
CREATE TABLE ... SELECT statements .creat table ...select对基于语句的复制【SBR】是不安全的。
Temporary tables 。GTIDsg不支持CREATE TEMPORARY TABLE AND DROP TEMPORARY TABLE .
【Preventing execution of unsupported statements】阻止不支持语句的执行。为了防止GTID受到不支持语句的影响而失败,在参与复制的Server上都要使用enforce-gtid-consistency操作。
sql_slave_skip_counter用于跳过不支持的事务【这在GTIDs不支持】。
在gtid_mode=ON时不要进行mysql_upgrade,因为Mysql_update会用MyiSam引擎改变一些系统表。
也不要在gtid_mode=ON时进行mysqldump文件的导入。
基于GTID复制的步骤
环境配置:
master server1 192.168.200.112
slave server2 192.168.200.113
在主DB服务器上建立复制帐号。
在主库执行命令
grant all on *.* to gtids@'192.168.200.%' identified by '123456';
配置主数据库服务器
修改配置文件
vim /etc/my.cnf
log_bin =on
server-id=1
gtid-mode=on
enforce_gtid_consistency:强制事务一致性,保证事务的安全
注意:如果使用了基于事务点日志配置,下面两种情况不能使用
1.create table 。。select
2.在事务中使用create temporary table 建立临时表,使用关联更新事务表和非事务表。
配置从服务器
vim /etc/my.cnf
server-id=2
log_bin=on
gtid-mode=on
enforce-gtid-consistency
建议配置
read_only=on
保证从服务器数据安全性
master_info_repository=TABLE
relay_log_info_repository=TABLE
从服务器连接主服务器的信息和中继日志存放咱 master_info,和relay_log中。
初始化从服务器数据。
从主库导出数据
mysqldump --single-transaction --master-data=2 --all-databases --triggers --routines --events -uroot -p >all.sql
可以使用 scp 命令将数据从主库机器copy 到从库:
scp all.sql root@192.168.200.113:/jsaas
从库导入数据
mysql -uroot -p < all.sql
启动基于GTID的复制
change master to
MASTER_HOST='192.168.200.112',
MASTER_PORT=3308,
MASTER_USER='gtids',
MASTER_PASSWORD='123456',
master_auto_position=1;
可能报错的情况:
@@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty
在命令行下执行命令:
reset master;
后重启mysql 服务。
start slave;
show slave status \G;
在启动slave时报错。
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
解决办法:
reset slave;重置slave
再启动 slave
start slave;
测试同步:
1.在主库创建一张表,插入记录。
2.在从库查询验证是否正确,经验证配置正确。