GTID原理与使用(一)

374 阅读4分钟

基本概念和组成

  GTID(Global Transaction Identifiner)全局事务标识符,是MySQL对于一个已提交事务全局唯一的编号,在本实例甚至主从复制环境都保证全局唯一。

  GTIDserver_uuidtransaction_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作用

  1. 简单的实现 failover,不用以前那样在需要找 log_file 和 log_pos。
  2. GTID用来代替classic的复制方法,不在使用binlog+pos开启复制。而是使用master_auto_postion=1的方式自动匹配GTID断点进行复制。
  3. 支持GTID后,备库启动时不再需要通过位点信息从主库来拉取binlog,而是根据备库本身已执行和拉取的gtid去主库查找第一个未执行的GTID,从此GTID位置开始拉取binlog;
  4. 一个 GTID 在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。
  5. GTID是连续的没有空洞的,保证数据的一致性,零丢失
  6. 根据 GTID 可以快速的确定事务最初是在哪个实例上提交的。

使用GTID限制

  1. 主从库的表存储引擎必须是一致的

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

  master:对一个innodb表做一个多sql更新的事物,效果是产生一个GTID。   slave:假设对应的表是MYISAM引擎,执行这个GTID的第一个语句后就会报错,因为非事务引擎一个sql就是一个事务。

  当从库报错时简单的stop slave; start slave;就能够忽略错误。但是这个时候主从的一致性已经出现问题,需要手工的把slave差的数据补上,这里要将引擎调整为一样的,slave也改为事务引擎。

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

  事务中混合多个存储引擎,就会产生多个 GTID。当使用 GTID 时,如果在同一个事务中,更新包括了非事务引擎(如 MyISAM)和事务引擎(如 InnoDB)表的操作,就会导致多个 GTID 分配给了同一个事务。

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

  2. 不支持sal_slave_skip_counter

  mysql在主从复制时如果要跳过报错,可以采取以下方式跳过SQL(event)组成的事务,但GTID不支持以下方式。set global SQL_SLAVE_SKIP_COUNTER=1;start slave sql_thread