一、什么是GTID?
GTID即全局事务ID(global transaction identifier),GTID实际上是由server_uuid:transaction_id组成的。其中server_uuid是一个MySQL实例的唯一标识,存放在数据目录的auto.cnf文件下,transaction_id是在事务提交的时候由系统顺序分配的一个序列号,并且随着事务提交单调递增。
二、为什么使用GTID?
GTID是MySQL5.6版本引入的一个有关于主从复制的重大改进,相对于之前版本基于Binlog文件+Position的主从复制,基于GTID的主从复制,数据一致性更高,主从数据复制更健壮,主从切换、故障切换不易出错,很少需要人为介入处理。另外,根据GTID可以知道事务最初是在哪个实例上提交的。(全局唯一性,趋势递增)
三、工作原理
要么主从全部开启GTID模式,要么全部关闭GTID模式。
1、master事务提交时会产生GTID,一同记录到binlog日志中。
2、slave端的i/o线程将变更的binlog,写入到本地的relay log中。
3、slave端的sql线程从relay log中获取GTID,然后对比slave端的系统变量@@GLOBAL.gtid_executed或者系统表mysql.gtid_executed。
4、如果有记录,说明该GTID的事务已经执行,slave会忽略。
5、如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
注:是否写入slave端的binlog由参数log_slave_updates决定。(有多个级联节点时,必须开启)
四、相关参数及表
配置参数:
server_id:设置MySQL实例的server_id,每个server_id不能一样
gtid_mode=ON:MySQL实例开启GTID模式
enforce_gtid_consitency=ON:使用GTID模式复制时,需要开启参数,用来保证数据的一致性。
log-bin: MySQL必须要开启binlog
binlog_format=ROW: binlog格式为row
log-slave-updates=1:决定SLAVE从Master接收到更新且执行是否记录到SLAVE的binlog中
skip-slave-start=1(可选): 当SLAVE数据库启动的时候,SLAVE不会启动复制
需理解的其他参数:
gtid_owned:这既是一个Global级别的变量,又是一个Session级别的变量,是只读变量 。Global级别的gtid_owned表示当前实例正在执行中的GTID,以及对应的线程id。Session级别的gtid_owned一般情况下是空的。
gtid_purged:这是一个Global级别的变量,可动态修改。表示当前实例中已经被purge掉的GTID集合,很明显gtid_purged是gtid_executed的子集。但是gtid_purged也不是可以随意修改的,必须在@@global.gtid_executed是空的情况下,才可以动态设置gtid_purged。
mysql.gtid_executed表:存储执行过的gtid集合(持久化)
@@GLOBAL.gtid_executed变量:内存中存储执行过的gtid集合
@@SESSION.GTID_NEXT变量:下一次事务的ID号。(可在binlog中查看)
五、使用gtid进行复制的限制
由于基于GTID的复制依赖于事务,因此在使用时不支持MySQL中可用的某些功能。
1、非事务性存储引擎的更新
使用GTID时,使用非事务性存储引擎(如MyISAM)对表的更新不能在与使用事务性存储引擎(如InnoDB)的表的更新相同的语句或事务中进行。此限制是由于对使用非事务性存储引擎的表的更新与对同一事务中使用事务存储引擎的表的更新混合可能导致将多个GTID分配给同一事务。
2、CREATE TABLE … SELECT 语句
CREATE TABLE … SELECT对于基于语句的复制是不安全的。使用基于行的复制时,此语句实际上记录为两个单独的事件 - 一个用于创建表,另一个用于将源表中的行插入刚刚创建的新表中。当在事务中执行此语句时,在某些情况下,这两个事件可能会接收相同的事务标识符,这意味着slave将跳过包含插入的事务。因此,使用基于GTID的复制时不支持CREATE TABLE … SELECT。
3、临时表
使用GTID时(即,enforce_gtid_consistency系统变量设置为ON时),事务,过程,函数和触发器内不支持CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE语句。可以在启用GTID的情况下使用这些语句,但仅限于任何事务之外,并且仅使用autocommit = 1。
4、防止执行不受支持的语句
要防止执行会导致基于GTID的复制失败的语句,必须在启用GTID时使用–enforce-gtid-consistency选项启动所有服务器。
5、跳过事务
使用GTID时不支持sql_slave_skip_counter = n(这个参数指跳过n个event)
6、Ignoring servers
使用GTID时,不推荐使用CHANGE MASTER TO语句的IGNORE_SERVER_IDS选项,因为已经应用的事务会自动被忽略。在启动基于GTID的复制之前,请检查并清除之前在相关服务器上设置的所有忽略的服务器ID列表。 可以为各个通道发出的SHOW_SLAVE_STATUS语句显示已忽略的服务器ID列表(如果有)。 如果没有列表,则Replicate_Ignore_Server_Ids字段为空。
7、GTID mode and mysqldump
如果目标服务器的二进制日志中没有GTID,则可以将使用mysqldump创建的转储导入到启用了GTID模式的MySQL服务器中。
8、GTID mode and mysql_upgrade
当服务器在启用全局事务标识符(GTID)的情况下运行时(gtid_mode = ON),请不要通过mysql_upgrade启用二进制日志记录(–write-binlog选项)。
六、查看slave状态
备库执行:
show slave status\G
七、异常同步处理
第一种:如果是修复主从复制中的异常,如果是在确认错误可以跳过的情况下,可以使用如下的方式:
stop slave;
set gtid_next=‘xxxxxxx:N’; --指定下一个事务执行的版本,即想要跳过的GTID
begin;
commit; --注入一个空事物
set gtid_next=‘AUTOMATIC’ --自动的寻找GTID事务。
start slave; --开始同步
注:处理前确认跳过的事务在binlog中执行的是什么?是否可跳过。
第二种:对于master上的binlog被清理,slave上找不到对应的binlog,需要跳过主库上所有被清理的binlog。
在主库执行show variables like ‘%gtid_purged%’,看主库清理的日志的范围。
stop slave;
reset master;
set global gtid_purged=‘uuid:1-n’;
start slave;
注:处理前确认跳过的事务在binlog中执行的是什么?是否可跳过。
八、其他
1、在通过备份恢复数据时,一定要将var目录中的auto.cnf删掉,让MySQL启动时自己生成uuid。
2、在传统的主从复制中,slave端不用开启binlog;但是在GTID主从复制中,必须开启binlog。
3、slave端在接受master的binlog时,会校验GTID值。
4、为了保证主从数据的一致性,多线程同时执行一个GTID。




