赞
踩
每提交一个事务,当前执行线程都会拿到一个唯一标示符GTID,此标示符不仅在源MySQL是唯一的,在复制环境中所有的MySQL示例中都是唯一的
通过show master status或者show slave status来查看
- mysql> show master status \G
- *************************** 1. row ***************************
- File: mysqlbinlog.000018
- Position: 194
- Binlog_Do_DB:
- Binlog_Ignore_DB:
- Executed_Gtid_Set: 79e1e785-7d7c-11e9-b4e4-000c29209533:1-8
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
MySQL 5.7.5之后可以通过mysql库的gtid_executed表来查看GTID
gtid_mode为ON或者ON_PERMISSIVE时,GTID才会保存在mysql.gtid_executed中
- mysql> show create table mysql.gtid_executed \G
- *************************** 1. row ***************************
- Table: gtid_executed
- Create Table: CREATE TABLE `gtid_executed` (
- `source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.',
- `interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.',
- `interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.',
- PRIMARY KEY (`source_uuid`,`interval_start`)
- ) ENGINE=InnoDB DEFAULT CHARSET=latin1
- 1 row in set (0.00 sec)
-
- mysql> select * from mysql.gtid_executed;
- +--------------------------------------+----------------+--------------+
- | source_uuid | interval_start | interval_end |
- +--------------------------------------+----------------+--------------+
- | 79e1e785-7d7c-11e9-b4e4-000c29209533 | 1 | 7 |
- | 79e1e785-7d7c-11e9-b4e4-000c29209533 | 8 | 8 |
- +--------------------------------------+----------------+--------------+
- 2 rows in set (0.00 sec)
随着数据库的不断更新,mysql.gtid_executed会存入很多数据占用空间,所以服务器会定期对mysql.gtid_executed表进行压缩,压缩率通过gtid_executed_compression_period
- mysql> show variables like '%executed_%';
- +----------------------------------+-------+
- | Variable_name | Value |
- +----------------------------------+-------+
- | gtid_executed_compression_period | 1000 |
- +----------------------------------+-------+
- '1000表示表的压缩在每1000个事务后执行,0代表不压缩'
还有一种压缩情况
当开启binlog,但是没有启用gtid_executed_compression_period时,binlog文件的切换,会引起mysql.gtid_executed的自动压缩
mysql.gtid_executed的压缩线程
- mysql> select * from performance_schema.threads where name like '%gtid%' \G
- *************************** 1. row ***************************
- THREAD_ID: 28
- NAME: thread/sql/compress_gtid_table
- TYPE: FOREGROUND
- PROCESSLIST_ID: 3
- PROCESSLIST_USER: NULL
- PROCESSLIST_HOST: NULL
- PROCESSLIST_DB: NULL
- PROCESSLIST_COMMAND: Daemon
- PROCESSLIST_TIME: 24278
- PROCESSLIST_STATE: Suspending
- PROCESSLIST_INFO: NULL
- PARENT_THREAD_ID: 1
- ROLE: NULL
- INSTRUMENTED: YES
- HISTORY: YES
- CONNECTION_TYPE: NULL
- THREAD_OS_ID: 1850
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启动之后,继续使用传统复制模式
1、2都可直接使用change master搭建
- gtid-mode=on
- enforce-gtid-consistency=1
- log_bin=masterbinlog
- binlog_format=row
- 从库要开启skip-slave-start=1,避免slave启动之后,继续使用传统复制模式
1、利用备份方式获取master的数据及GTID范围,使用innobackupex备份,会将该信息保存在xtrabackup_binlog_info中
- [root@redhat-1-6 backup]# cat xtrabackup_binlog_info
- 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
在复制中偶尔会遇到主键冲突或者从库找不到记录的错误,传统复制模式可以使用
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模式的复制,跳过一个事务,需要利用一个空事务来完成
- 1、通过分析last_error的报错和master的binlog得到产生错误的GTID
- 2、stop slave
- 3、SET gtid_next='GTID'; '设置下一个GTID为我们要跳过的GTID'
- 4、begin;commit; '执行一个空事务'
- 5、SET gtid_next='AUTOMATIC' '设置GTID自动获取'
- 6、start slave
跳过事务使slave正常运行,在处理问题是非常方便的,但是可能会出现事务不一致的情况,所以在跳过之前,分析一下binlog并且记录下来,分析是否可以跳过,跳过之后查看主从是否一致,是否需要修复数据,所以一定要慎用!!
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
- mysql> show status like '%Ongoing_anonymous_transaction_count%';
- +-------------------------------------+-------+
- | Variable_name | Value |
- +-------------------------------------+-------+
- | Ongoing_anonymous_transaction_count | 0 |
- +-------------------------------------+-------+
该状态表示已标记为匿名的正在进行的事务数量,为0则表示无事务等待被处理
6、在每台服务器上设置gtid_mode=on,开启GTID
set @@global.gtid_mode=on;
7、修改my.cnf,修改之后,即使数据库重启,配置也是生效的
- gtid-mode=on
- enforce-gtid-consistency=1
注意:开启GTID之后复制还是基于binlog position的,还需将复制调整为GTID模式
- stop slave;
- change master to master_auto_position=1;
- start slave;
1、关闭基于GTID的复制模式,调整为传统复制模式
- stop slave; 假设复制关闭后复制的位置为mysqlbinlog.000020:506
- mysql> change master to master_auto_position=0,master_log_file='mysqlbinlob.000020',master_log_pos=506;
- start slave;
2、在每台服务器上设置gtid_mode=on_permissive
3、在每台服务器上设置gtid_mode=off_permissive
4、等待所有服务器上的gtid_owned为空
- mysql> show variables like '%gtid_owned%';
- +---------------+-------+
- | Variable_name | Value |
- +---------------+-------+
- | gtid_owned | |
- +---------------+-------+
这表示正在由线程执行的全局GTID集合
5、等待所有的slave上都复制完成匿名事务
- mysql> show status like '%Ongoing_anonymous_transaction_count%';
- +-------------------------------------+-------+
- | Variable_name | Value |
- +-------------------------------------+-------+
- | Ongoing_anonymous_transaction_count | 0 |
- +-------------------------------------+-------+
6、在每一台服务器关闭GTID
set @@global.gtid_mode=off;
7、修改配置文件,确保重启配置也是生效的
- gtid-mode=off
- enforce-gtid-consistency=off
由于基于GTID的复制依赖于事务,所以在使用GTID的时候,有些MySQL的特性是不支持的
当一个事务中的更新包含了非事务引擎(如MyISAM)和事务引擎(如innodb)表的操作,就会导致多个GTID分配给同一个事务
如果主从库的存储引擎不一致,例如一个是事务引擎,一个是非事务引擎,则会导致事务和GTID之间的一对一关系被破坏,从而导致基于GTID的复制不能正确进行
因为基于行模式复制时,该语句实际上被记录为两个单独的事务,一个是创建表,另一个是将原表中的数据插入到新表中,一些情况下,这两个事务可能收到相同的事务id,这意味着包含插入的事务可能被从库跳过
使用GTID复制时,不支持create_temporary table和drop temporary table,但是在autocommit=1的情况下可以创建临时表,master不产生GTID,所以不会同步到salve,但是在删除临时表的时候,产生GTID会导致主从中断
因为mysql_upgrade的过程要创建或修改系统表(非事务引擎),所以不建议在开启GTID的实例上使用带有--write-binlog选项的mysql_upgrade
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。