Linux下MySQL主从复制(GTID)+读写分离(ProxySQL)-实施笔记

GTID( Global Transaction Identifier)全局事务标识。GTID 是 5.6 版本引入的一个有关于主从复制的重大改进,相对于之前版本基于 Binlog 文件 + Position 的主从复制,基于 GTID 的主从复制,数据一致性更高,主从数据复制更健壮,主从切换、故障切换不易出错,很少需要人为介入处理。

GTID是对于一个已提交事务的编号,并且是一个全局唯一的编号。GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识,保存在mysql数据目录下的$datadir/auto.cnf文件里。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。下面是一个GTID的具体形式:3E11FA47-71CA-11E1-9E33-C80AA9429562:23。如果复制结构中,任意两台服务器uuid重复的话(比如直接冷备份时,auto.conf中的内容是一致的),在启动复制功能的时候会报错。这时可以删除auto.conf文件再重启mysqld。

GTID的工作原理:

从服务器连接到主服务器之后,把自己执行过的GTID (Executed_Gtid_Set: 即已经执行的事务编码)<SQL线程> 、获取到的GTID (Retrieved_Gtid_Set: 即从库已经接收到主库的事务编号) <IO线程>发给主服务器,主服务器把从服务器缺少的GTID及对应的transactions发过去补全即可。当主服务器挂掉的时候,找出同步最成功的那台从服务器,直接把它提升为主即可。如果硬要指定某一台不是最新的从服务器提升为主, 先change到同步最成功的那台从服务器, 等把GTID全部补全了,就可以把它提升为主了。

  简单概述如下:

1.当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中。

2.binlog传输到slave,并存储到slave的relaylog后,读取这个GTID的这个值设置gtid_next变量,即告诉Slave,下一个要执行的GTID值。

3.sql线程从relay log中获取GTID,然后对比slave端的binlog是否有该GTID。

4.如果有记录,说明该GTID的事务已经执行,slave会忽略。

5.如果没有记录,slave就会执行该GTID事务,并记录该GTID到自身的binlog,在读取执行事务前会先检查其他session持有该GTID,确保不被重复执行。

6.在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

GTID的生命周期:gtid的生命周期对于配置和维护基于gtid的复制至关重要。

1.GTID在主库提交事务的flush阶段产生,但并非所有事务都会产生GTID(如只读事务)

2.事务拿到GTID后,会生成Gtid_log_event,在提交的时候会记录到binlog event事务的开头。

3.在binlog写满或者服务器关闭的时候,服务器会把这个binlog所有的GTID写到mysql.gtid_executed表里进行持久化。

4.当事务提交后,事务会把分配到的Gtid添加到gtid_executed系统变量中。gtid_executed里面记录的所有提交的GTID事务,它是实时的。

5.binlog发送到从库的relay log中,从库读取binlog event里面的Gtid,并设置自己的gtid_next变量为读到的gtid值,从库在进行下一个事务,就会使用这个GTID来提交事务。

6.从库先会判断当前是否有线程正持有这个Gtid,也会确定这个Gtid对应的事务是否已经执行过了。已经执行的事务会被跳过。gtid_owned专门用来存储当前正被线程持有的Gtid,事务提交成功,也会把Gtid从gtid_owned集合里释放。

7.如果从库开启了binlog,GTID也会伴随Gtid_event_log写到binlog里,这和主库的逻辑一样,在重启和binlog写满的逻辑也一样。

8.如果从库没有开启binlog,从库的GTID只能通过gtid_executed表来存储,每次事务提交,GTID会实时写入到gtid_executed表中,这个时候gtid_executed变量和gtid_executed表的数据是同步的。

 GTID的优缺点:

优点:

1.保证同一个事务在某slave上绝对只执行一次,没有执行过的gtid事务总是会被执行。

2.不用像传统复制那样保证binlog的坐标准确,因为根本不需要binlog以及坐标。

3.故障转移到新的master的时候很方便,简化了很多任务。

4.很容易判断master和slave的数据是否一致。只要master上提交的事务在slave上也提交了,那么一定是一致的。

5.当然,MySQL提供了选项可以控制跳过某些gtid事务,防止slave第一次启动复制时执行master上的所有事务而导致耗时过久。

6.虽然对于row-based和statement-based的格式都能进行gtid复制,但建议采用row-based格式。

缺点:

1.不支持非事务引擎。

2.在一个复制组中,必须要求统一开启GTID或者是关闭GTID

3.不支持sql_slave_skip_counter(一般用这个来跳过基于binlog主从复制出现的问题)。

4.不允许一个SQL同时更新一个事务引擎表和非事务引擎表。

5.为了保证事务的安全性,create table ... select无法使用。不能使用create temporary table创建临时表。不能使用关联更新事务表和非事务表。

MySQL GTID复制部署过程如下。

MySQL5.7 GTID复制官方文档:https://dev.mysql.com/doc/refman/5.7/en/replication-gtids.html

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgzyyj.html