暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MYSQL特性-GTID

老子瞎说 2018-05-28
271

本文的大部分内容都来自于《MYSQL运维内参》,是本不错的参考书,讲的内容偏深,嗯,挺好。怀着对作者的敬畏之心,参考一下。

 

GTID是全局事务标识符,是mysql5.6版本开始在主从复制方面推出的重量级特性。有了GTID,一个事务在集群中就不再孤独,在每一个节点中,都存在具有相同标识符的兄弟们和它做伴,同一个事务,在同一个节点中出现多次的情况,也不会再出现了。GTID的出现,直接的效果是,每一个事务在集群中具有了唯一性的意义,这在运维方面意义非凡,给DBA带来很大的便利性,因为再也不需要为不断的找点而烦恼了。

GTID的便利性:

  • 根据GTID可以快速地知道事务最初是在哪个实例上提交的。

  • 基于GTID搭建主从复制更加简单,确保每个事务只会被执行一次。

  • 基于GTID复制,可以更方便地实现replicationfailover。因为不用像传统模式复制那样去找master_log_filemaster_log_pos.

  • 同样是在mysqlGroup Replication中,集群使用GTID来标识事务,或者叫冲突验证,用于跟踪每个实例上提交的事务,确定那些事务可能有冲突。

  • GTID的引入,让每一个事务在集群事务的海洋中有了秩序,使得DBA在运维中做集群变迁时更加方便。

什么是GTID

每提交一个事务,当前执行线程都会拿到一个唯一标识符,此标识符不仅对其源mysql实例是唯一的,而且在给定的复制环境中的所有mysql实例中也是唯一的。所有事务与其GTID之间都是一一对应的,GTID格式如下:

GTID = server_uuid:sequence_id

Server_uuid是服务器自动生成的唯一标识符,sequence_id是在事务提交时由系统顺序分配的一个序列号,递增的。可以通过show master statusshow slave status查看当前实例执行过的GTID信息,它以集合的方式呈现。

mysql> show master status\G;

*************************** 1. row  ***************************

             File: mysql-bin.000035

          Position: 456

      Binlog_Do_DB:

 Binlog_Ignore_DB:

Executed_Gtid_Set:  8785f0fc-285c-11e8-ae27-000c2990e30b:1-307119

其中,本实例的server_uuid8785f0fc-285c-11e8-ae27-000c2990e30b,共提交了307119个事务。GTID始终保存在主实例中,可以通过检查二进制日志来确定事务的来源。此外,一旦在给定的mysql实例中提交了事务,具有相同GTID的事务便会被该服务器忽略。而且,在主实例上提交的事务在从库上只可以应用一次,这有助于保持主从的一致性。

GTID生命周期

  1. master上执行一个事务,master将会产生一个GTID信息,并保存binlog中。

  2. 将二进制日志信息发送到slave所在的服务器上,并且存储在relay log中,slave读取GTID并设置其gtid_next值,从而告知slave必须使用此GTID记录下一个事务。

  3. Slave首先验证其是否已经在自己的二进制日志中使用过该GTID号。如果未使用过,slave则写入该GTID,应用其事务,并将事务写入二进制日志。Slave首先读取和检查事务的GTID,在提交事务之前,slave不仅要保证slave没有应用具有该GTID的事务,而且还要保证没有其他回话已经读取了该GTID但尚未提交,即不允许多个客户端应用相同的事务。

  4. 由于gitd_next不为空,slave不会尝试为该事务生成新的GTID,而是从gtid_next中读取GTID值并写入二进制日志中,来标识一个事务的GTID值,之后在集群中都会始终对应这个GTID值,且不会发生改变,起到身份证标签的作用。

直接上图:(说明该图是盗用别人的,特别形象就拿过来使用一下,如侵权联系删除。)

 

上面提到gtid_next,当GTID复制集发生冲突时,可以使用该参数跳过冲突的事务:

跳过一个事务的方法。
通过show slave status\G找到冲突的GTID.
然后执行
SET gtid_next = '
冲突的GTID';
BEGIN;COMMIT;
SET gtid_next = 'AUTOMATIC';
START SLAVE;
这就可以跳过一个事务了,原理在于通过执行一个空事务代替master传递过来的冲突事务.

 

GTID搭建主从

在日常运维中,GTID带来的最方便的作用就是搭建和维护主从复制,这也是DBA日常工作中最常用的操作。GTID的主从模式替代了mysql前期版本中利用二进制日志文件的名称和日志位置的做法,使用GTID使操作和维护都变得更加简洁和可靠。

搭建主从时,需要注意的mysql参数

相对于传统搭建主从来说,GTID搭建主从模式需要在配置文件中指定如下参数:

  • Server_id:设置mysql实例的server_id,每个实例的server_id不能一样。

  • Gtid_mode=ON:mysql实例开启GTID模式。

  • Enforce_gtid_consitency=ON:使用GTID模式复制时,用此参数保证GTID的一致性。

  • Log-binmysql必须开启binlog.

  • Log-slave-updates=1:决定slavemaster接收到的更新执行完后,执行的binlog是否记录到slavebinlog中,建议开启。

  • Binlog_format=ROW:建议binlog_format使用ROW格式,其他格式可能造成数据不一致。

  • Skip-slave-start=1:当slave数据库启动的时候,slave不会自动开启复制。

搭建主从

根据master的情况,常见的基于GTID模式的主从搭建有一下几种方式(复制的相关帐号和权限已经授予,并且GTID已经开启)。

  • Master是新搭建的且无数据:针对这种情况,直接利用change master 语句搭建。

mysql>  change master to

    -> master_host='10.10.10.1',

    -> master_port=3306,

    -> master_user='repl',

    -> master_password='repl',

    -> master_auto_position=1;

  • Master运行不久,所有的binlog保留完整:针对这种情况,可以使用类似上面的方式搭建,直接利用change master语句,从master上获取所有的GTID,然后在slave上执行。优点是简单快捷,缺点是如果binlog相对较多,slave同步时间相对较长,可能导致网络压力过大。

  • Master具有大量数据:针对这种情况,可能不能使用上面的方法,因为原始的binlog可能已经被删除,无法从头开始获取所有的GTID信息。那么需要从master上获取数据及该数据的GTID范围,然后通过在slave上设置选项(gtid_purged)的方式来跳过这些GTID。最后通过change master的方式搭建主从。

GTID的限制

由于基于GTID的复制依赖于事务,所以在使用GTID时,有些mysql特性不支持。

  • 事务中混合多个存储引擎,会产生多个GTID

  • 主从库的表存储引擎不一致,会导致数据不一致。

  • 基于GTID模式复制,不支持createtable … select语句。

因为使用基于行模式的复制时,该语句实际上被记录为两个单独的事件,一个是创建表,一个是插入操作。当在事务中执行该语句时,在一些情况下,这两个事务可能接收到相同的事务ID,这意味着包含插入的事务被从库跳过。

  • 不支持createtemporary tabledrop temporary table.autocommit=1的情况下,可以创建临时表,master创建临时表不产生GTID信息,所以不会同步到slave上,但是删除临时表时产生的GTID会导致主从中断。

  • 不推荐在GTID模式的实例上进行mysql_upgrade,因为mysql_upgrade的过程要创建或修改系统表(非事务引擎)。但是mysql8.0之后,系统表是支持事务的,也就支持该操作了。


文章转载自老子瞎说,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论