GTID 工作原理介绍
一、 GTID基本概念 ( Global transaction identifiers ) 1.MySQL-5.6.2开始支持,MySQL-5.6.10后完善,GTID 分成两部分(uuid:trans_id),一部分是服务的UUid,UUID保存在mysql数据目录的auto.cnf文件中,这是一个非常重要的文件,不能删除,这一部分是不会变的。另外一部分就是事务ID了,随着事务..
一、 GTID基本概念 ( Global transaction identifiers )
1.MySQL-5.6.2开始支持,MySQL-5.6.10后完善,GTID 分成两部分(uuid:trans_id),一部分是服务的UUid,UUID保存在mysql数据目录的auto.cnf文件中,这是一个非常重要的文件,不能删除,这一部分是不会变的。另外一部分就是事务ID了,随着事务的增加,值一次递增,如下
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+--------------------------------------------+
| binlog.000016 | 1562 | | | ad3690ff-bc92-11e8-b175-005056ae0385:1-45 |
+---------------+----------+--------------+------------------+--------------------------------------------+
GTID:ad3690ff-bc92-11e8-b175-005056ae0385:1-45
UUID:ad3690ff-bc92-11e8-b175-005056ae0385
transactionId:1-362
2.如果复制结构中,直接冷备份,那么主从中的auto.cnf内容是一致的。在启动复制功能的时候会报错。可以删除auto.cnf,然后重启mysql。
二,GTID工作原理简单介绍
1.master更新数据的时候,会在事务前产生GTID,一同记录到binlog日志中。
2.slave端的io线程将binlog写入到本地relay log中。
3.然后SQL线程从relay log中读取GTID,设置gtid_next的值为该gtid,然后对比slave端的binlog是否有记录
4.如果有记录的话,说明该GTID的事务已经运行,slave会忽略
5.如果没有记录的话,slave就会执行该GTID对应的事务,并记录到binlog中
三,GTID工作原理深入理解
gtid在master和slave上持久化保存,即使删除了日志,也会记录到previous_gtid中。
1.binlog文件中记录的格式是先记录gtid,然后再记录事务相关的操作。
2.gtid_next 是基于会话的,不同会话的gtid_next不同。
3.如果mysql是5.6版本,那么主从必须开启log_slave_updates参数,此时slave对比自己的binlog查看是否有记录。如果mysql是5.7版本,那么主从不需要开启此参数(级联主从除外),mysql5.7提供了gtid_excuted系统表来记录复制的信息,以此减少从库的压力。
例如"gtid_executed 5ad9cb8e-2092-11e7-ac95-000c29bf823d:1-6",表示该server_uuid上执行了从1到6的事务。
4. 5.6版本,slave在应用relay log的时候不是提交后才将gtid写入到自己的binlog中,而是判断gtid不存在后立即写入binlog。通过这种在执行事务前先检查gtid并写gtid到binlog中的机制,可以保证没有其他会话读取了该gtid却没有提交而导致事务重复执行的情况。
如果当前会话读取了该gtid,并将该gtid立即写入binlog(不管是否已经执行该事务),那么其他会话总能读取到binlog中的该gtid,然后其他会话就会放弃该事务。总之,一个事务是不允许多个会话并行执行或多次执行的。
5.slave在应用relaylog的时产生的binlog中的gtid是master的gtid,所以在整个复制架构中GTID是不变的,即使在多个连环主从中也不会变。例如:
ServerA --->ServerB ---->ServerC
GTID从在ServerA ,ServerB,ServerC 中都是一样的。
四,GTID的特点
1.一个事务对应唯一一个ID,一个GTID对应的事务在同一台服务器上只能执行一次。
2.GTID复制与普通复制最大的区别就是 不需要指定二进制文件名和位置
3.当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中;binlog中先记录gtid,紧跟着再记录事务相关的操作。
4.MySQL提供了选项可以控制跳过某些gtid事务,防止slave第一次启动复制时执master上的所有事务而导致耗时过久。
如何跳过?
mysql> reset master;
mysql> set @@global.gtid_purged='a659234f-6aea-11e8-a361-000c29ed4cf4:1-54';
mysql> change master to master_host='192.168.100.21',master_port=3306,master_auto_position=1;
mysql> start slave;
5.对于row模式和statement模式都可以进行gtid复制,建议使用row模式。
五,GID的限制
- 不支持非事务引擎(从库报错,stopslave; start slave; 忽略)
- 不支持create table … select 语句复制(主库直接报错)
- 不允许在一个SQL同时更新一个事务引擎和非事务引擎的表
- 在一个复制组中,必须要求统一开启GTID或是关闭GTID
- 开启GTID需要重启(5.7中可能不需要)
- 开启GTID后,就不在使用原来的传统的复制方式
- 对于create temporary table 和drop temporary table语句不支持
- 不支持sql_slave_skip_counte
六,那么GTID复制是怎么实现自动同步,自动对应位置的呢?
例如:ServerC <-----ServerA ----> ServerB
主机:ServerA
备机:ServerB,ServerC
当主机serverA挂了之后,需要将serverB提升为主机(可以通过MHA实现),serverC连接到serverB上。
此时,serverC先在自己的二进制文件中找到从serverA传过来的最新的GTID,将最新的GTID传给serverB,然后serverB就会从这个GTID的下个GTID开始发送事务给serverC。
这种自我寻找复制位置的模式减少了事务丢失的可能性和故障恢复的时间。
七,配置gtid
主:
[mysqld]
datadir=/data
socket=/data/mysql.sock
log-bin=/data/master-bin # 必须项
sync-binlog=1 # 建议项
binlog_format=row # 建议项
server-id=100 # 必须项
log-error=/data/error.log
pid-file=/data/mysqld.pid
enforce_gtid_consistency=on # gtid复制需要加上的必须项
gtid_mode=on # gtid复制需要加上的必须项
从:
[mysqld]
datadir=/data
socket=/data/mysql.sock
log-bin=/data/master-slave-bin # mysql 5.6必须项,mysql 5.7非必须项
sync-binlog=1 # 建议项
binlog_format=row # 建议项
relay-log=/data/slave-bin # 必须项
server-id=110 # 必须项
log-error=/data/error.log
pid-file=/data/mysqld.pid
enforce_gtid_consistency=on # 必须项
gtid_mode=on # 必须项
八,gtid相关状态行和变量
- Retrieved_Gtid_Set:在开启了gtid复制(即gtid_mode=on)时,slave在启动io线程的时候会检查自己的relay log,并从中检索出gtid集合。也就是说,这代表的是slave已经从master中复制了哪些事务过来。检索出来的gtid不会再请求master发送过来。
- Executed_Gtid_Set:在开启了gtid复制(即gtid_mode=on)时,它表示已经向自己的binlog中写入了哪些gtid集合。注意,这个值是根据一些状态信息计算出来的,并非binlog中能看到的那些。举个特殊一点的例子,可能slave的binlog还是空的,但这里已经显示一些已执行gtid集合了。
- Auto_Position:开启gtid时是否自动获取binlog坐标。1表示开启,这是gtid复制的默认值。
- gtid_mode:是否开启gtid复制模式。只允许on/off类的布尔值,不允许其他类型(如1/0)的布尔值,实际上这个变量是枚举类型的。要设置 gtid_mode=on ,必须同时设置 enforce_gtid_consistency 开。在MySQL 5.6中,还必须开启 log_slave_updates ,即使是master也要开启。
- enforce_gtid_consistency:强制要求只允许复制事务安全的事务。 gtid_mode=on 时必须显式设置该项,如果不给定值,则默认为on。应该尽量将该选项放在 gtid_mode 的前面,减少启动mysqld时的检查。
-
- 不能在事务内部创建和删除临时表。只能在事务外部进行,且autocommit需要设置为1。
- 不能执行 create table ... select 语句。该语句除了创建一张新表并填充一些数据,其他什么事也没干。
- 不能在事务内既更新事务表又更新非事务表。
- gtid_executed:已经执行过的GTID。 reset master 会清空该项的全局变量值。
- gtid_purged:已经purge掉的gtid。要设置该项,必须先保证 gtid_executed 已经为空,这意味着也一定会同时设置该项为空。在slave上设置该项时,表示稍后启动io线程和SQL线程都跳过这些gtid,slave上设置时应该让此项的gtid集合等于master上 gtid_executed 的值。
- gtid_next:表示下一个要执行的gtid事务。
需要注意,master和slave上都有gtid_executed和gtid_purged,它们代表的意义有时候是不同的。
更多推荐
所有评论(0)