Gtid的核心就是给每个事务分配一个惟一的id,根据这个ID就知道这个事务是在哪个节点执行。鉴于它有上述的特色,可让主从方便的作failover,集群能够经过gtid作冲突检查,由于每个事务都有标记,dba在作集群迁移的时候也更加的方便。每执行一个事务,当前执行线程都会拿到一个惟一的(整个集群环境惟一)的事务标识符 格式:GTID=server_uuid:seq_id server_uuid其实是一个32字节+1个字节的”/0”的字符串,在mysql启动的时候会自动去读datadir中的auto.cnf文件,若是没没有找到就自动建立一个。seq_id是给事务分配的一个序列号。 在GTID中,同一个gtid对应的事务只能被执行一次,这个和基于传统模式复制的GTID不同,在传统模式的复制中可能会由于指定了错误position和logfile致使事务被重复执行。 Gtid是在事务commit阶段调用mysql_binlog:orderd_commit生成的。最终gtid会被写入到binlog中,注意,如今生成的是下一个事务的gtid(gtid_next)。mysql
之因此须要进行GTID的持久化工做是由于gtid_executed等这些变量都是在内存中的,在数据库重启以后须要肯定哪些GTID是执行过的,哪些GTID是没有执行过的。在5.7.6以前版本的数据库中,只能经过binlog来进行持久化,一个事务在写入binlog以前先重gtid_next中获取这个事务的gtid写入到binlog中,而后在进行事务的写入,在事务的commit阶段生成gtid_next的值。鉴于上诉机制,在5.7.5如下的版本中,slave端必需要开启log_slave_updates才能够。 对于5.7.6以上的版本中,引入了mysql.gtid_executed这个表来进行gtid的持久化,全部执行过的gtid都会被记录在该表中。经过gtid_executed_compression_period参数去设置执行多个个事务压缩该表一次。git
gtid_owned,保存了服务器上正在实行的GTID事务列表以及拥有他们(负责执行)的server_id。主要用于多线程复制,在应用线程处理gtid事务的时候会一直拥有该事务的gtid,因此说当gtid_owned有值的时候说明当前应用线程正在应用gtid事务,在事务commit或者回滚以后就会释放。 gtid_executed,哪些gtid事务被执行了,信息是放在内存中。 gtid_purged,因为binlog被删除或者expire所致使的gtid信息丢失,对于主库来讲该变量表示再也不当前binlog中的gtid集合,对于备库来讲该变量表示已经执行过的gtid,因此若是使用mysqldump来初始化一个开启了gtid备库的时候要特别注意在start slave以前须要先reset master而后在设置GTID_PURGED变量。sql
关于gtid_executed修改的时间,对于主库来讲,在binlog关闭的时候,gtid_executed、gtid_purged、mysql.gtid_executed都不会更新,也不能开启。在binlog开启的时候,在binlog发生rotate的时候更新gtid_executed信息,这个时候mysql.executed表不是实时更新的,可是gtid_executed变量是实时更新的。关于gtid_executed变量的更新,在ordered_commit flush阶段产生gtid,因此gtid_executed是实时更新的。关于gtid_purge变量的更新时间,在purge binlog或者超过expire时间的时候会更新gtid_purge信息。 对于从库来讲,在没有开启log_slave_updates的状况下,无论有没有启用binlog结果都是gtid_executed实时更新,gtid_executed变量的值是实时更新的。关于gtid_purge变量的更新,由于没有binlog记录,全部gtid_purged的值是实时更新的,binlog开启同时log_slave_updates开启的状况下,由于有binlog event记录gtid,mysql.executed不须要实时更新,它更新的状况和主库是同样的,只是在binlog发生切换的时候或者超过expire的时候更新。 对于mysql.gtid_executed来讲,在reset master的时候会清空这个表,在set global gitd_purged的时候,设置本表,同时主库发生日志轮转的时候也会修改本表。数据库
一、确认事务的内容是能够跳过的 二、stop slave 三、设置gtid_next='master_uuid:xxx'; 四、注册空事务 五、设置gtid_next为automatic 六、启动slave 在gtid_executed中,若是slave本身作了写入,那么也会记录在gtid_executed中,格式为slave_uuid:xxx服务器
##转换多线程
一、在全部节点上面修改enforce_gtid_consistency=warn,在设置了这个参数以后,当存在违法gtid一致性的event时候就会报错 SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN; 设置完成以后运行一段时间,确认无任何报错以后能够继续进行下一步,若是有报错须要修改应用 二、在确认无告警以后 SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;性能
三、设置gtid_mode 在哪一个服务器上面先执行这个是可有可无的 SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE; 设置了以后表示新事务是匿名的,同时运行复制时使用gtid或者匿名事务 四、设置gtid_mode=ON_PERMISSIVE; SET global gtid_mode=ON_PERMISSIVE; 先在哪一个服务器上面执行没有关系,设置了以后表示新事务是gtid事务,同时容许复制时候使用gtid或者匿名事务。 五、确认匿名事务为0,全部节点 SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT'; 有的时候可能发现这个值为0或者不为0,可是没有关系,只要有一次为0就能够了 必需要确认全部匿名事务均已经复制完成才能继续,建议经过上述命令方式+binlog的方式,由于若是下一步执行了gtid_mode=on,那么那些未有复制的匿名事务就不能复制了。 六、开启gtid,而且写入到my.cnf文件 SET @@GLOBAL.GTID_MODE = ON;ui
一、记录复制的位置以后中止io sql线程 mh01@3307>stop slave io_thread; 查看slave状态确认,确认数据已经所有同步 Exec_Master_Log_Pos: 47477668 Read_Master_Log_Pos: 47477668 二、change master操做 mh01@3307>change master to master_auto_position=0,master_log_file='mh01-3306.000017',master_log_pos=47477668; 三、在每一台服务器上面设置gtid为on_permissive模式 set global gtid_mode=on_permissive; 四、在每一台服务器上面设置gtid为off_permissive模式 set global gtid_mode=off_permissive;
5 五、等待全部gtid_owned为空,为空表示已经没有gtid事务正在被执行。 select @@global.gtid_owned;线程
七、等待全部匿名事务完成 show global status like 'ONGOING_ANONYMOUS_TRANSACTION_COUNT'; 注意,有的时候会显示0或者非0,可是没有关系,在前面的步骤完成后只要有一次显示0就能够了。 八、关闭gtid set global gtid_mode=off; 重要的是要了解包含GTID事务的日志在下一步以后没法使用。 在继续以前,您必须确保拓扑中的任何位置都不存在GTID事务。 九、写入配置到my.cnf文件日志
##其余
该参数用于定义是否支持快速gtid扫描,5.7.5以前胃false,以后为true,如今讨论什么状况下可能发生binlog全扫描的问题。 注意的问题:在gtid关闭,simplified_binlog_gtid_recovery=false的状况下,无论什么版本在重启的时候都须要进行binlog的全扫描。在binlog被删除或者被purge的状况下,5.7.6以后的数据库也须要进行binlog的全扫描,可是这个版本以前的就不须要了,由于这个版本以前的数据库不支持在线修改gtid状态。另外,若是simplified_binlog_gtid_recovery=true,那么在旧版本的数据库中可能不能获取正确的gtid值。 在5.7.6以上的数据库中,simplified_binlog_gtid_recovery=true是最好的选择。由于在获取gtid值的时候只须要扫描最新和最旧的binlog就能够了,性能很好。5.7.6如下版本的数据库中通常不会使用gtid来切换数据库。由于没有mysql.executed的支持,必需要开启log_slave_updates,会带来性能上面的影响。