GTID的基本概念与应用

一、GTID

1.1 gtid的基本概念

gtid的全称为全局事务标识符(global transaction identifiner),是MySQL 5.6引入的一个特性。gtid保证了MySQL的每一个事务都有一个全局唯一的标识,该标识在本实例甚至主从复制环境都保证全局唯一。

GTID = server_uuid:sequence_id

server_uuid是一个32字节+1字节(/0)的字符串,MySQL第一次启动时生成,并将该信息写入datadir目录下的auto.cnf文件。如果该文件丢失,MySQL会重新生成一个新的server_uuid。相同的server_uuid下的事务对应的sequence_id在binlog文件中是递增且连续有序的,他们以集合的方式呈现。

1.2 gtid带来的便利性

1)通过gtid定位该事务来自哪个实例

2)搭建主从复制不再需要指定binlog文件以及具体的位点信息,而是通过全局唯一的gtid来做复制,MySQL通过gtid来验证冲突并确保每个事务只会被执行一次。

3)方便DBA的运维管理,快速改变主从复制关系

1.3 GTID在主从复制中如何工作?

1)master执行的每一个变更操作都生成一个gtid值,并且会把该值记录在binlog中用来主从复制,后续择机更新gtid_executed表记录

2)主从复制模式下,start slave后,从库会将自身执行过的gtid集合信息发送给主库,主库将从库未执行过的binlog信息发送给从库

3)从库读取relaylog中把该值设置为当前的gtid_next值,对具体的事务进行应用,择机更新gtid_executed表记录。期间主库不断的将新产生的binlog event发送至从库

从库应用主库的事务时不会生成新的gtid值,而是将读取的gtid_next的值记录在自己的binlog文件中

1.4 gtid的维护

1、gtid_executed表

1)MySQL 5.7.5之前

  • 该版本下从库必须开始binlog并且设置log_slave_updates=on来保证从库执行过的gtid信息全部记录在binlog中

2)MySQL 5.7.5之后

  • MySQL 5.7.5之后新增的mysql.gtid_executed表
  • 若不开启binlog,每个事务的gtid信息都会记录到gtid_executed表中
  • 若开启binlog且开启log_slave_updates,每个事务的gtid信息不仅会记录到gtid_executed表中,也会在记录在binlog日志中的GTID_LOG_EVENT中

3)概览

  • gtid持久化介质
  • gtid_executed表会随着数据库的不断更新而存储较多的gtid信息
  • MySQL对定期对gtid_executed表进行压缩,通过参数gtid_executed_compression_period进行控制,默认该表记录1000条记录后就进行一次压缩
  • MySQL binlog日志切换也会模式对该表进行一次压缩

2、gtid_executed变量

  • 该变量为一个gtid set的形式,存储在内存中,表示当前实例执行了哪些gtid事务
  • “show slave status\G”、"show master status"中记录的Executed_Gtid_Set都来自该参数的值

3、gtid_purged变量

  • 该变量为gtid set的形式,存储在内存中,表示当前实例已经丢失了(执行过)哪些gtid事务
  • 通过purge命令或者expire_logs_days参数自动删除历史binlog文件后,会导致历史gtid信息丢失
  • 在搭建从库时,我们可以手动指定gtid_purge值来表示当前从库已经执行过了哪些gtid,从该gtid之后重新开始复制

4、gtid_mode

gtid_mode值含义
ON使用gtid模式,新生产的事务为gtid事务,且只能复制gtid事务
ON_PERMISSIVE新生成的事务为gtid事务,同时可以复制gtid事务或者匿名事务
OFF_PERMISSIVE新生成的事务为匿名事务,同时可以复制gtid事务或者匿名事务
OFF关闭gtid模式,新生成的事务为匿名事务,且只能复制匿名事务

5、enforce_gtid_consistency

enforce_gtid_consistency值含义
ON不允许任何交易违反GTID一致性
WARN允许所有事务违反GTID一致性,但是在这种情况下会生成警告,MySQL 5.7.6新增
OFF允许所有事务违反GTID一致性

6、在主/从库中gtid_executed表、gtid_executed变量、gtid_purged变量更新时机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bzvv6DUI-1593157274284)(http://note.youdao.com/yws/res/56812/FD085068A28544C9A48478E0440293BC)]

7、GTID模块初始化以及binlog_gtid_simple_recovery参数的理解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kUzYKNIB-1593157274289)(http://note.youdao.com/yws/res/56820/33267B0128BE4C9C82E3A5BBCE732C9C)]

二、gtid的应用

2.1 gtid搭建主从

1、gtid相关参数设置

root@mysql57 15:30:  [(none)]> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |        //默认为on,不建议关闭。为快速从binlog日志中找到gtid信息
| enforce_gtid_consistency         | ON        |        //该参数必须设置为on,保证gtid的一致性
| gtid_executed_compression_period | 1000      |        //指定gtid_executed表压缩
| gtid_mode                        | ON        |        //打开gtid模式
| gtid_next                        | AUTOMATIC |        
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+
8 rows in set (0.00 sec)

2、搭建主从需要关注参数

server_id                       //主从库server-id必须不一样
log_bin                         //主库必须打开binlog日志
binlog_format=row               //建议使用row模式
gtid_mode=on                    //开启gtid
enforce_gtid_consitency=on      //保证gtid一致性
log_slave_updates               //5.6版本中使用gtid必须开启该参数,5.7.5以后该参数决定gtid信息持久化介质是哪些

3、使用gtid模式搭建主从复制

CHANGE MASTER TO
  MASTER_HOST='master2.example.com',
  MASTER_USER='replication',
  MASTER_PASSWORD='password',
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1;

2.2 传统复制架构 -> gtid复制架构

1、在MySQL 5.7.6之前,需要重启数据库修改

1)关闭主库,停止业务写入

2)等待从库追上主库的复制

3)修改主库、从库配置文件,添加“gtid_mode=on,enforce_gtid_consitency=on”,启动从库时指定–skip-slave-start避免从库启动时继续使用传统模式复制

4)检查主从复制是否修改为gtid模式,且复制状态是否正常

2、在MySQL 5.7.6之后,支持在线修改

1)在每台服务器上设置enforce_gtid_consistency=warn,允许所有事务可以违反gtid的一致性

root@mysql57 20:43:  [(none)]> set global enforce_gtid_consistency=warn;
Query OK, 0 rows affected (0.00 sec)

root@mysql57 20:43:  [(none)]> show variables like '%enforce%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| enforce_gtid_consistency | WARN  |
+--------------------------+-------+
1 row in set (0.01 sec)

2)在每台服务器上设置enforce_gtid_consistency=on,保证所有事务都不可以违反gtid的一致性

root@mysql57 20:44:  [(none)]> set global enforce_gtid_consistency=on;
Query OK, 0 rows affected (0.00 sec)

root@mysql57 20:44:  [(none)]> show variables like '%enforce%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| enforce_gtid_consistency | ON    |
+--------------------------+-------+
1 row in set (0.00 sec)

3)在每台服务器上设置gtid_mode=off_permissive,表示新事务是匿名事务,同时允许复制的事务是gtid或是匿名事务

root@mysql57 20:47:  [repl_test]> show variables like '%gtid%';
+----------------------------------+----------------+
| Variable_name                    | Value          |
+----------------------------------+----------------+
| binlog_gtid_simple_recovery      | ON             |
| enforce_gtid_consistency         | ON             |
| gtid_executed_compression_period | 1000           |
| gtid_mode                        | OFF_PERMISSIVE |
| gtid_next                        | AUTOMATIC      |
| gtid_owned                       |                |
| gtid_purged                      |                |
| session_track_gtids              | OFF            |
+----------------------------------+----------------+
8 rows in set (0.00 sec)

4)在每台服务器上设置gtid_mode=on_permissive,表示新的事务是gtid事务,同时允许复制的事务是gtid或者匿名事务

root@mysql57 20:47:  [repl_test]> set global gtid_mode=on_permissive;
Query OK, 0 rows affected (0.02 sec)

root@mysql57 20:48:  [repl_test]> show variables like '%gtid%';
+----------------------------------+---------------+
| Variable_name                    | Value         |
+----------------------------------+---------------+
| binlog_gtid_simple_recovery      | ON            |
| enforce_gtid_consistency         | ON            |
| gtid_executed_compression_period | 1000          |
| gtid_mode                        | ON_PERMISSIVE |
| gtid_next                        | AUTOMATIC     |
| gtid_owned                       |               |
| gtid_purged                      |               |
| session_track_gtids              | OFF           |
+----------------------------------+---------------+
8 rows in set (0.00 sec)

5)在每台从服务器上等待状态参数Ongoing_anonymous_transaction_count的状态值为0,该参数表示正在处理的匿名事务数,只有该状态值降为0才可进行下一步

root@mysql 20:48:  [(none)]> show global status like '%transaction%';
+-------------------------------------+-------+
| Variable_name                       | Value |
+-------------------------------------+-------+
| Ongoing_anonymous_transaction_count | 0     |
+-------------------------------------+-------+
1 row in set (0.00 sec)

6)在每台服务器上设置gtid_mode=on,此后从库只会复制gtid事务

root@mysql57 20:49:  [repl_test]> set global gtid_mode=on;
Query OK, 0 rows affected (0.02 sec)

root@mysql57 20:50:  [repl_test]> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | ON        |
| gtid_executed_compression_period | 1000      |
| gtid_mode                        | ON        |
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+
8 rows in set (0.00 sec)

7)修改配置文件“gtid_mode=on,enforce_gtid_consitency=on”,保证数据库重启后仍是gtid

8)修改当前复制为gtid复制

root@mysql 20:51:  [(none)]> stop slave;
Query OK, 0 rows affected (0.01 sec)

root@mysql 20:51:  [(none)]>
root@mysql 20:51:  [(none)]> change master to master_auto_position=1;
Query OK, 0 rows affected (0.01 sec)

9)检查复制状态以及复制模式

root@mysql 20:51:  [(none)]> show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Executed_Gtid_Set: ca3051f8-a265-11ea-923e-00163e15aea9:1-6
Auto_Position: 1

2.3 gtid复制架构 -> 传统复制架构

1)转笔从库主从复制,并修改当前复制为传统复制模式

##停止主从复制,并查看当前复制的位点信息
root@mysql 22:46:  [(none)]> stop slave;
Query OK, 0 rows affected (0.00 sec)

root@mysql 22:46:  [(none)]> show slave status\G
              Master_Log_File: binlog.000005
          Read_Master_Log_Pos: 1968
                Auto_Position: 1

##修改gtid复制为传统复制                
root@mysql 22:46:  [(none)]> change master to master_log_file='binlog.000005',master_log_pos=1968,master_auto_position=0;
Query OK, 0 rows affected (0.02 sec)

root@mysql 22:47:  [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)

##检查复制模式以及复制状态
root@mysql 22:47:  [(none)]> show slave status\G
              Master_Log_File: binlog.000005
          Read_Master_Log_Pos: 2775
                Auto_Position: 0          

2)将每个服务器的gtid_mode设置为on_permissive,表示新的事务还是使用gtid,同时允许复制gtid事务和匿名事务

root@mysql 22:47:  [(none)]> set global gtid_mode=on_permissive;
Query OK, 0 rows affected (0.01 sec)

root@mysql 22:51:  [(none)]> show variables like '%gtid%';
+----------------------------------+---------------+
| Variable_name                    | Value         |
+----------------------------------+---------------+
| binlog_gtid_simple_recovery      | ON            |
| enforce_gtid_consistency         | ON            |
| gtid_executed_compression_period | 1000          |
| gtid_mode                        | ON_PERMISSIVE |
| gtid_next                        | AUTOMATIC     |
| gtid_owned                       |               |
| gtid_purged                      |               |
| session_track_gtids              | OFF           |
+----------------------------------+---------------+
8 rows in set (0.00 sec)

3)将每个服务器的gtid_mode设置为off_permissive,表示新的事务为匿名事务,同时允许复制gtid事务和匿名事务

root@mysql 22:51:  [(none)]> set global gtid_mode=off_permissive;
Query OK, 0 rows affected (0.01 sec)

root@mysql 22:51:  [(none)]> show variables like '%gtid%';
+----------------------------------+----------------+
| Variable_name                    | Value          |
+----------------------------------+----------------+
| binlog_gtid_simple_recovery      | ON             |
| enforce_gtid_consistency         | ON             |
| gtid_executed_compression_period | 1000           |
| gtid_mode                        | OFF_PERMISSIVE |
| gtid_next                        | AUTOMATIC      |
| gtid_owned                       |                |
| gtid_purged                      |                |
| session_track_gtids              | OFF            |
+----------------------------------+----------------+
8 rows in set (0.00 sec)

4)查看从库gtid_owned,等待该参数为空,表示当前已经无正在复制中的gtid事务,且后续全部都是匿名事务

root@mysql 22:54:  [(none)]> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | ON        |
| gtid_executed_compression_period | 1000      |
| gtid_mode                        | OFF       |
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+
8 rows in set (0.00 sec)

5)关闭从库的gtid模式

root@mysql 22:54:  [(none)]> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | ON        |
| gtid_executed_compression_period | 1000      |
| gtid_mode                        | OFF       |
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+
8 rows in set (0.00 sec)

##若主库此刻修改gtid_mode会出现报错:
root@mysql57 22:54:  [repl_test]> set global gtid_mode=off;
ERROR 3111 (HY000): SET @@GLOBAL.GTID_MODE = OFF is not allowed because replication channel '' is configured in AUTO_POSITION mode. Execute CHANGE MASTER TO MASTER_AUTO_POSITION = 0 FOR CHANNEL '' before you set @@GLOBAL.GTID_MODE = OFF..

6)修改配置文件,保证重启后也不再使用gtid

gtid_mode=off
enforce_gtid_consistency=off

三、gtid的限制

由于gtid对事务一致性的要求,会导致以下一些问题无法支持:

1、事务中包含对多个存储引擎的查询更新,会导致对该事务分配多个gtid

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

3、无法使用create table … select 的语句

root@mysql57 23:49:  [repl_test]> create table t5 select * from t1;
ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.

row模式下,create table … select其实会转换为两个单独的事务,一个是create table,一个是insert数据。当在事务中执行该语句时,一些情况下会导致两个事务分配了相同的事务id,这意味着从库会忽略掉插入数据的事务,从而导致主从数据不一致

4、只有在acticommit=1的情况下,才支持使用create temporary table和drop temporary table语句

root@mysql57 23:34:  [repl_test]> show master status;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000010 |     1430 |              |                  | ca3051f8-a265-11ea-923e-00163e15aea9:1-21 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)

root@mysql57 23:50:  [repl_test]> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)

root@mysql57 23:50:  [repl_test]> create temporary table tmp_t1 like t1;
Query OK, 0 rows affected (0.00 sec)

root@mysql57 23:50:  [repl_test]> show master status;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000010 |     1430 |              |                  | ca3051f8-a265-11ea-923e-00163e15aea9:1-21 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)

root@mysql57 23:51:  [repl_test]> drop temporary table tmp_t1;
Query OK, 0 rows affected (0.00 sec)

root@mysql57 23:51:  [repl_test]> show master status;
+---------------+----------+--------------+------------------+-------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+-------------------------------------------+
| binlog.000010 |     1644 |              |                  | ca3051f8-a265-11ea-923e-00163e15aea9:1-22 |
+---------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)


##从库
root@mysql 23:51:  [repl_test]> show tables;
+---------------------+
| Tables_in_repl_test |
+---------------------+
| t1                  |
| t2                  |
| t3                  |
| t4                  |
+---------------------+
4 rows in set (0.00 sec)

root@mysql 23:51:  [repl_test]> show master status;
+------------------+----------+--------------+------------------+-------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+------------------+----------+--------------+------------------+-------------------------------------------+
| mysql-bin.000013 |     1588 |              |                  | ca3051f8-a265-11ea-923e-00163e15aea9:1-22 |
+------------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)

root@mysql 23:51:  [repl_test]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Retrieved_Gtid_Set: ca3051f8-a265-11ea-923e-00163e15aea9:18-22
            Executed_Gtid_Set: ca3051f8-a265-11ea-923e-00163e15aea9:1-22
                Auto_Position: 1

master创建临时表不产生gtid信息,导致从库无法同步该操作,而后续删除临时表的操作会产生相应的gtid信息并同步到从库,这种情况下就会导致主从复制报错中断

5、不推荐在开启gtid模式的实例上使用mysql_upgrate

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值