MySQL GTID Replication:html
从MySQL5.6开始增长了强大的GTID(Global Transaction ID,全局事务ID)这个特性,用来强化数据库的主备一致性, 故障恢复, 以及容错能力。用于取代过去传统的主从复制(即:基于binlog和position的异步复制)。mysql
借助GTID,在发生主备切换的状况下,MySQL的其余slave能够自动在新主上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减小了人为设置复制position发生误操做的风险。另外,基于GTID的复制能够忽略已经执行过的事务,减小了数据发生不一致的风险。sql
GTID组成:数据库
GTID是由server_uuid和事务id组成的,即GTID=server_uuid:transaction_id。
server_uuid,是在MySQL第一次启动时自动生成并持久化到auto.cnf文件(存放在数据目录下,每台机器的server_uuid都不同。
transaction_id,是一个从1开始的自增计数,表示在这个主库上执行的第n个事务。MySQL会保证事务与GTID之间的1:1映射,如:b6af5b5c-666f-11e9-bed3-000c29b85ea6:1
表示在以b6af5b5c-666f-11e9-bed3-000c29b85ea6为惟一标识的MySQL实例上执行的第1个数据库事务。
一组连续的事务能够用 "-" 链接的事务序号范围表示。例如:b6af5b5c-666f-11e9-bed3-000c29b85ea6:1-5
服务器
基于GTID复制的优势:多线程
一、根据传统的复制原理,当链接发生故障时,须要从新链接到master主机,须要找到binlog和position,而后change master to 链接到master主机,此过程须要人工来作,比较麻烦,也容易出错,尤为是master写操做较多时,更不容易肯定position,若是flush table with read lock,势必会影响到线上业务。而GTID复制方式不须要找master的binlog和position,只须要知道master的ip、端口、帐号密码,便可进行复制,MySQl会经过内部机制自动找点同步(MASTER_AUTO_POSITION=1)
简单来讲就是:简化复制。传统复制是基于file和position来实现的,而file和position是人为肯定的,file还好一些,可是position倒是实时变更的,难以肯定,除非对全库加读锁,但这势必会对线上业务产生影响,GTID会自动找position进行数据同步并发
二、多线程复制(基于库),在MySQL5.6之前的版本,slave的复制是单线程的。一个事件一个事件的读取应用。而master是并发写入的,因此延迟是避免不了的。惟一有效的方法是把多个库放在多台slave,这样又有点浪费服务器。在MySQL5.6里面,咱们能够把多个表放在多个库,这样就可使用多线程复制,当只有1个库,多线程复制是没有用的(即:所谓的并行复制)
简单来讲就是:跟多线程复制相关。多线程复制是基于组提交方式实现的,而组提交信息是存储在GTID中的异步
GTID的做用:ide
一、根据GTID能够知道事务最初是在哪一个实例上提交的
二、GTID的存在方便了Replication的Failoverui
GTID复制实现的工做原理:
一、master更新数据时,会在事务前产生GTID,一同记录到binlog日志中
二、slave端的I/O线程将变动的binlog,写入到本地的relay log中
三、SQL线程从relay log中获取GTID,而后对比slave端的binlog是否有记录(因此MySQL5.6 slave端必须开启binlog)
四、若是有记录,说明该GTID的事务已经执行,slave会忽略
五、若是没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog
六、在解析过程当中会判断是否有主键,若是没有就用二级索引,若是没有就用所有扫描
GTID使用限制:
一、 MySQL5.7以后才开始支持动态切换GTID相关的参数
二、 不支持CREATE TABLE ... SELECT statements
三、 不支持CREATE TEMPORARY TABLE statements inside transactions
四、 transaction or statement 既更新了事务表又更新了非事务表
五、 使用GTID复制从库跳过错误时,不支持执行sql_slave_skip_counter参数的语法
GTID相关状态变量介绍:
推荐阅读MySQL官网英文原著
Master、Slave上均可以查看GTID相关的状态变量
mysql> show global variables like '%gtid%';
+--------------------------+------------------------------------------+
| Variable_name | Value |
+--------------------------+------------------------------------------+
| enforce_gtid_consistency | ON |
| gtid_executed | b6af5b5c-666f-11e9-bed3-000c29b85ea6:1-7 |
| gtid_mode | ON |
| gtid_owned | |
| gtid_purged | |
+--------------------------+------------------------------------------+
5 rows in set (0.00 sec)
如下内容是笔者从博客、论坛等收集的资料,不保证正确性,仅供参考:
一、gtid_executed
在当前实例上执行过的GTID集合,实际上包含了全部记录到binlog中的事务。因此,设置set sql_log_bin=0后执行的事务不会生成binlog事件,也不会被记录到gtid_executed中。执行reset master能够将该变量清空
二、gtid_purged
binlog不可能永久停留在服务器上,须要进行按期清理(如经过expire_logs_days),不然早晚它会把磁盘空间用完。gtid_purged用于记录已经被清除了的binlog事务集合,它是gtid_executed的子集。只有gtid_executed为空时才能手动设置该变量,此时会同时更新gtid_executed为和gtid_purged相同的值。gtid_executed为空意味着要么以前没有启动过基于GTID的复制,要么执行过reset master。执行reset master时一样也会把gtid_purged置空,即始终保持gtid_purged是gtid_executed的子集。
三、gtid_next
会话级变量,指示如何产生下一个GTID。可能的取值:
AUTOMATIC,自动生成下一个GTID,实现上是分配一个当前实例上还没有执行过的序号最小的GTID
ANONYMOUS,设置后执行事务不会产生GTID
显式指定的GTID,能够指定任意形式合法的GTID值,但不能是当前gtid_executed中的已经包含的GTID,不然,下次执行事务时会报错
四、gtid_mode
是否开启GTID复制功能
五、enforce-gtid-consistency = ON
启动强制GTID的一致性,若是开启GTID功能则此参数必需要开启;slave在作同步复制时,无须找到binlog日志和POS点,直接change master to master_auto_position=1便可,自动根据GTID进行同步数据。
延伸:
多线程复制:
MySQL5.6以前的版本,同步复制是单线程的、队列的,只能一个一个执行。在MySQL5.6里,能够作到多个库之间的多线程复制。例如数据库里,存放着用户表、商品表、价格表、订单表,那么将每一个业务表单独放在一个库里,这时就能够作到多线程复制,但一个库里的表,多线程复制是无效的(由于同一个库进行多线程复制到Slave上时会形成问题);每一个数据库仅能使用一个线程(即:MySQL5.6多线程复制基于库),复制涉及到多个数据库时多线程复制才有意义。Slave上多线程复制的控制参数为slave-parallel-workers=0(0表示禁用多线程功能)
题外:
本文的主要做用是记录GTID的用途、优缺点、使用限制、状态变量介绍等,内容大可能是从MySQL官网或者一些博客论坛摘录的理解。本着实践是检验真理的惟一标准的原则,记录本文更多的做用为未来实际应用的时候作铺路。因此,笔者不保证内容准确性,仅供参考。欢迎业内大佬指出其中不当之处,在此先表示感谢!