当前位置:   article > 正文

一篇读懂MySQL的GTID_mysql查询当前最新gtid show master

mysql查询当前最新gtid show master

GTID的出现,使每一个事务在集群中有了唯一性的意义

每提交一个事务,当前执行线程都会拿到一个唯一标示符GTID,此标示符不仅在源MySQL是唯一的,在复制环境中所有的MySQL示例中都是唯一的

通过show master status或者show slave status来查看

  1. mysql> show master status \G
  2. *************************** 1. row ***************************
  3. File: mysqlbinlog.000018
  4. Position: 194
  5. Binlog_Do_DB:
  6. Binlog_Ignore_DB:
  7. Executed_Gtid_Set: 79e1e785-7d7c-11e9-b4e4-000c29209533:1-8

GTID的生命周期

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

2、将binlog信息发送到slave,并保存在relay log 中

3、slave首先验证其是否已经在自己的binlog中使用过了该GTID,如果没有使用,slave则写入该GTID,并用应用其事务,并将事务写入自己的binlog

4、slave不会为该事务生成新的GTID,而是从gtid_next中读取GTID值并写入binlog中,用来标识事务,且在集群中该事务会始终对应这个GTID

gtid_executed表及其压缩

MySQL 5.7.5之后可以通过mysql库的gtid_executed表来查看GTID

gtid_mode为ON或者ON_PERMISSIVE时,GTID才会保存在mysql.gtid_executed中

  1. mysql> show create table mysql.gtid_executed \G
  2. *************************** 1. row ***************************
  3. Table: gtid_executed
  4. Create Table: CREATE TABLE `gtid_executed` (
  5. `source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.',
  6. `interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.',
  7. `interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.',
  8. PRIMARY KEY (`source_uuid`,`interval_start`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=latin1
  10. 1 row in set (0.00 sec)
  11. mysql> select * from mysql.gtid_executed;
  12. +--------------------------------------+----------------+--------------+
  13. | source_uuid | interval_start | interval_end |
  14. +--------------------------------------+----------------+--------------+
  15. | 79e1e785-7d7c-11e9-b4e4-000c29209533 | 1 | 7 |
  16. | 79e1e785-7d7c-11e9-b4e4-000c29209533 | 8 | 8 |
  17. +--------------------------------------+----------------+--------------+
  18. 2 rows in set (0.00 sec)

随着数据库的不断更新,mysql.gtid_executed会存入很多数据占用空间,所以服务器会定期对mysql.gtid_executed表进行压缩,压缩率通过gtid_executed_compression_period

  1. mysql> show variables like '%executed_%';
  2. +----------------------------------+-------+
  3. | Variable_name | Value |
  4. +----------------------------------+-------+
  5. | gtid_executed_compression_period | 1000 |
  6. +----------------------------------+-------+
  7. '1000表示表的压缩在每1000个事务后执行,0代表不压缩'

还有一种压缩情况

当开启binlog,但是没有启用gtid_executed_compression_period时,binlog文件的切换,会引起mysql.gtid_executed的自动压缩

mysql.gtid_executed的压缩线程

  1. mysql> select * from performance_schema.threads where name like '%gtid%' \G
  2. *************************** 1. row ***************************
  3. THREAD_ID: 28
  4. NAME: thread/sql/compress_gtid_table
  5. TYPE: FOREGROUND
  6. PROCESSLIST_ID: 3
  7. PROCESSLIST_USER: NULL
  8. PROCESSLIST_HOST: NULL
  9. PROCESSLIST_DB: NULL
  10. PROCESSLIST_COMMAND: Daemon
  11. PROCESSLIST_TIME: 24278
  12. PROCESSLIST_STATE: Suspending
  13. PROCESSLIST_INFO: NULL
  14. PARENT_THREAD_ID: 1
  15. ROLE: NULL
  16. INSTRUMENTED: YES
  17. HISTORY: YES
  18. CONNECTION_TYPE: NULL
  19. THREAD_OS_ID: 1850

利用GTID搭建主从关系

GTID最方便的就是搭建和维护主从复制,替代了基于binlog position的主从复制

搭建GTID主从复制,要注意开启参数,MySQL 5.7.6之后可以在线搭建

gtid-mode=on enforce-gtid-consistency=1 log_bin=masterbinlog binlog_format=row 从库要开启skip-slave-start=1,避免slave启动之后,继续使用传统复制模式

搭建GTID主从的三种情况

1、master是新搭建的,没有数据

2、master搭建不久,所有binlog保存完整

1、2都可直接使用change master搭建

  1. gtid-mode=on
  2. enforce-gtid-consistency=1
  3. log_bin=masterbinlog
  4. binlog_format=row
  5. 从库要开启skip-slave-start=1,避免slave启动之后,继续使用传统复制模式

3、master有大量的数据,最原始的binlog已被删除,无法从头开始获取所有GTID

1、利用备份方式获取master的数据及GTID范围,使用innobackupex备份,会将该信息保存在xtrabackup_binlog_info中

  1. [root@redhat-1-6 backup]# cat xtrabackup_binlog_info
  2. mysqlbinlog.000017 194 79e1e785-7d7c-11e9-b4e4-000c29209533:1-7

2、启动slave实例,并设置gtid_purged的值,跳过这段范围

SET @@GLOBAL.GTID_PURGED='79e1e785-7d7c-11e9-b4e4-000c29209533:1-7'

3、利用change master搭建主从复制

4、启动slave复制,会自动跳过这段GTID范围,拉去最新的GTID

如何跳过一个GTID

在复制中偶尔会遇到主键冲突或者从库找不到记录的错误,传统复制模式可以使用

mysql> set global sql_slave_skip_counter=1;

跳过这个事件,但是在GTID模式中,使用该命令则会报错

ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction

那我们如何跳过这个GTID呢

基于GTID模式的复制,跳过一个事务,需要利用一个空事务来完成

  1. 1、通过分析last_error的报错和master的binlog得到产生错误的GTID
  2. 2、stop slave
  3. 3SET gtid_next='GTID'; '设置下一个GTID为我们要跳过的GTID'
  4. 4begin;commit; '执行一个空事务'
  5. 5SET gtid_next='AUTOMATIC' '设置GTID自动获取'
  6. 6start slave

跳过事务使slave正常运行,在处理问题是非常方便的,但是可能会出现事务不一致的情况,所以在跳过之前,分析一下binlog并且记录下来,分析是否可以跳过,跳过之后查看主从是否一致,是否需要修复数据,所以一定要慎用!!

在线进行传统复制模式(基于binlog position)与GTID复制模式的转换

在线将传统复制模式改为GTID模式

1、在每一台服务器上设置enforce_gtid_consistency=warn

set @@global.enforce_gtid_consistency=warn;

这样设置之后,使得所有的事务都允许违反GTID的一致性,然后查看错误日志,在进行下一步之前,要确保错误日志中没有警告

2、在每一台服务器上设置enforce_gtid_consistency=on

set @@global.enforce_gtid_consistency=on;

确保所有的事务都不能违反GTID的一致性

3、在每台服务器上设置gtid_mode=off_permissive

set @@global.gtid_mode=off_permissive;

表示,新的事务是匿名的,同时允许复制的事务是为GTID或是匿名的

4、在每台服务器上设置gtid_mode=on_permissive

set @@global.gtid_mode=on_permissive;

表示新的事务使用GTID,同时允许复制的事务是为GTID或是匿名的

3,4都要确保执行才可以

5、确保Ongoing_anonymous_transaction_count=0

  1. mysql> show status like '%Ongoing_anonymous_transaction_count%';
  2. +-------------------------------------+-------+
  3. | Variable_name | Value |
  4. +-------------------------------------+-------+
  5. | Ongoing_anonymous_transaction_count | 0 |
  6. +-------------------------------------+-------+

该状态表示已标记为匿名的正在进行的事务数量,为0则表示无事务等待被处理

6、在每台服务器上设置gtid_mode=on,开启GTID

set @@global.gtid_mode=on;

7、修改my.cnf,修改之后,即使数据库重启,配置也是生效的

  1. gtid-mode=on
  2. enforce-gtid-consistency=1

注意:开启GTID之后复制还是基于binlog position的,还需将复制调整为GTID模式

  1. stop slave;
  2. change master to master_auto_position=1;
  3. start slave;

在线将GTID模式改为传统复制模式

1、关闭基于GTID的复制模式,调整为传统复制模式

  1. stop slave; 假设复制关闭后复制的位置为mysqlbinlog.000020:506
  2. mysql> change master to master_auto_position=0,master_log_file='mysqlbinlob.000020',master_log_pos=506;
  3. start slave;

2、在每台服务器上设置gtid_mode=on_permissive

3、在每台服务器上设置gtid_mode=off_permissive

4、等待所有服务器上的gtid_owned为空

  1. mysql> show variables like '%gtid_owned%';
  2. +---------------+-------+
  3. | Variable_name | Value |
  4. +---------------+-------+
  5. | gtid_owned | |
  6. +---------------+-------+

这表示正在由线程执行的全局GTID集合

5、等待所有的slave上都复制完成匿名事务

  1. mysql> show status like '%Ongoing_anonymous_transaction_count%';
  2. +-------------------------------------+-------+
  3. | Variable_name | Value |
  4. +-------------------------------------+-------+
  5. | Ongoing_anonymous_transaction_count | 0 |
  6. +-------------------------------------+-------+

6、在每一台服务器关闭GTID

set @@global.gtid_mode=off;

7、修改配置文件,确保重启配置也是生效的

  1. gtid-mode=off
  2. enforce-gtid-consistency=off

GTID的限制

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

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

当一个事务中的更新包含了非事务引擎(如MyISAM)和事务引擎(如innodb)表的操作,就会导致多个GTID分配给同一个事务

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

如果主从库的存储引擎不一致,例如一个是事务引擎,一个是非事务引擎,则会导致事务和GTID之间的一对一关系被破坏,从而导致基于GTID的复制不能正确进行

3、不支持create table ...select语句

因为基于行模式复制时,该语句实际上被记录为两个单独的事务,一个是创建表,另一个是将原表中的数据插入到新表中,一些情况下,这两个事务可能收到相同的事务id,这意味着包含插入的事务可能被从库跳过

4、不支持create_temporary table和drop temporary table

使用GTID复制时,不支持create_temporary table和drop temporary table,但是在autocommit=1的情况下可以创建临时表,master不产生GTID,所以不会同步到salve,但是在删除临时表的时候,产生GTID会导致主从中断

5、不推荐在GTID模式的实例上使用mysql_upgrade

因为mysql_upgrade的过程要创建或修改系统表(非事务引擎),所以不建议在开启GTID的实例上使用带有--write-binlog选项的mysql_upgrade

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/959330
推荐阅读
相关标签
  

闽ICP备14008679号