基本概念和组成
GTID(Global Transaction Identifiner)全局事务标识符,是MySQL对于一个已提交事务全局唯一的编号,在本实例甚至主从复制环境都保证全局唯一。
GTID由server_uuid和transaction_id两个共同组成,即GTID = server_uuid:transaction_id
server_uuid: 是一个Mysql实例的唯一标识,在Mysql第一次启动时,会自动生成并持久化到auto.cnf文件中。可以通过执行如下指令查看当前实例的server_uuid。
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| 4d7310e6-3fa1-11ed-a5d4-81f0301c00a8 |
+--------------------------------------+
transaction_id: 代表的是实例上已经提交的事务数量,transaction_id是一个从1开始的自增计数,在binlog文件中是递增且连续有序,通常以集合的方式呈现。
GTID开启与查看
可以通过指令查看gtid当前状态
mysql> select @@gtid_mode;
+-------------+
| @@gtid_mode |
+-------------+
| OFF |
+-------------+
GTID开启与查看
只有当 enforce_gtid_consistency = ON才允许 gtid_mode被设置为 ON。每一次修改 gtid_mode都会导致 binary log 发生一次切换,在操作时需考虑业务影响。MySQL 5.7版本,enforce_gtid_consistency设置成ON时,违反 GTID 一致性的 SQL 都会被拒绝,MySQL 8.0不受影响。
mysql> create table t1 as select * from tbl_good_info;
ERROR 1786(HY000):Statement violates GTID consistency:CREATE TABLE ... SELECT
在线开启
在线开启的方式,重启实例后设置会失效
mysql> set @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@GLOBAL.GTID_MODE = ON_PERMISSIVE;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@GLOBAL.GTID_MODE = ON;
Query OK, 0 rows affected (0.00 sec)
永久开启
永久开启需要修改配置目录下my.cnf文件,追加以下内容
gtid_mode = ON
enforce-gtid-consistency
GTID查看
MySQL 5.7引入系统表 mysql.gtid_executed ,用于存放所有执行过的GTID(在活动的binlog中的除外),但是由于不包含活动的binlog当中的GTID,因此需要查看精确值时可以查看 global variable gtid_executed 的值。
mysql> select * from mysql.gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| 4d7310e6-3fa1-11ed-a5d4-81f0301c00a8 | 1 | 3 |
+--------------------------------------+----------------+--------------+
mysql> show global variables like 'gtid_%';
+----------------------------------+------------------------------------------+
| Variable_name | Value |
+----------------------------------+------------------------------------------+
| gtid_executed | 4d7310e6-3fa1-11ed-a5d4-81f0301c00a8:1-6 |
| gtid_executed_compression_period | 0 |
| gtid_mode | ON |
| gtid_owned | |
| gtid_purged | |
+----------------------------------+------------------------------------------+
在binlog发生rotate(flush binary logs/达到max_binlog_size)或者关闭服务时,会把所有写入到binlog中的GTID信息写入到mysql.gtid_executed表。
mysql> flush logs;
Query OK, 0 rows affected (0.02 sec)
mysql> select * from mysql.gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| 4d7310e6-3fa1-11ed-a5d4-81f0301c00a8 | 1 | 6 |
+--------------------------------------+----------------+--------------+
GTID作用
- 简单的实现 failover,不用以前那样在需要找 log_file 和 log_pos。
- GTID用来代替classic的复制方法,不在使用binlog+pos开启复制。而是使用master_auto_postion=1的方式自动匹配GTID断点进行复制。
- 支持GTID后,备库启动时不再需要通过位点信息从主库来拉取binlog,而是根据备库本身已执行和拉取的gtid去主库查找第一个未执行的GTID,从此GTID位置开始拉取binlog;
- 一个 GTID 在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。
- GTID是连续的没有空洞的,保证数据的一致性,零丢失
- 根据 GTID 可以快速的确定事务最初是在哪个实例上提交的。
使用GTID限制
- 主从库的表存储引擎必须是一致的
主从库的表存储引擎不一致,就会导致数据不一致。如果主从库的存储引擎不一致,例如一个是事务存储引擎,一个是非事务存储引擎,则会导致事务和 GTID 之间一对一的关系被破坏,结果就会导致基于 GTID 的复制不能正确运行;
master:对一个innodb表做一个多sql更新的事物,效果是产生一个GTID。 slave:假设对应的表是MYISAM引擎,执行这个GTID的第一个语句后就会报错,因为非事务引擎一个sql就是一个事务。
当从库报错时简单的stop slave; start slave;就能够忽略错误。但是这个时候主从的一致性已经出现问题,需要手工的把slave差的数据补上,这里要将引擎调整为一样的,slave也改为事务引擎。
- 不允许一个SQL同时更新一个事务引擎和非事务引擎的表
事务中混合多个存储引擎,就会产生多个 GTID。当使用 GTID 时,如果在同一个事务中,更新包括了非事务引擎(如 MyISAM)和事务引擎(如 InnoDB)表的操作,就会导致多个 GTID 分配给了同一个事务。
-
在一个复制组中,必须要求统一开启GTID或是关闭GTID;
-
不支持sal_slave_skip_counter
mysql在主从复制时如果要跳过报错,可以采取以下方式跳过SQL(event)组成的事务,但GTID不支持以下方式。set global SQL_SLAVE_SKIP_COUNTER=1;start slave sql_thread。