1.MySQL gtid;
在MySQL5.6以及MySQL5.7 上使用 GTID,一直以来都有几个硬性限制。
CREATE TABLE ....SELECT;
CREATE TEMPORARY TABLE ...;
针对这两条SQL,如果想在GTID模式下使用,为了不破坏事务一致性,是被严格显示不允许的。
为了满足需求,一般会通过其他途径绕过这些限制。这个硬性限制随着MySQL8.0的新特性的发布,
连带着被间接取消掉。比如MySQL8.0的DDL原子性。
MySQL5.7环境下:
create table ...select ;这条语句 语义上分别属于两个隐式事务(一条DDL语句,一条DML语句)。
但在GTID开启后,单个语句只能给它分配一个GTID事务,如果强制使用,会直接报违反GTID一致性。
create table t1(id int primary key,log_date date);
insert t1 values(1,'2022-01-02');
create table t2 as select * from t2;
Error 1786(HY000):Statement violates GTID consistency:CREATE TABLE .. SELECT;
#替换方案
create table t2 like t1; #Like语句不插入数据。也不创建索引。
insert into t2 select * from t1;
对应的binlog 数据,将被拆分为2个事务。
对于显式临时表的床与删除,这样的DDL在GTID模式下也是禁止放在事务块里执行的。
(begin;commit;或者存储过程,存储函数,触发器等大事务块)。
begin;
create temporary table temp(id int);
ERROR:1787 :Statement violates GTID consistency:CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE;
把这类DDL语句放在事务块外面或者使用基于磁盘表的DDL语句来替代。
create temporary table temp2(id int,log_date date);
begin;
insert into temp2 values(100,'2025-05-20');
insert into temp1 select * from temp2;
commit;
#MySQL5.7不允许在事务块创建临时表。MySQL8.0允许在事务块里创建临时表。
2.MySQL8.0原生DDL原子性
所以解除了这两个GTID的限制。
对于create table ...as select * from ..; 语句。在MYSQL8.0版本中只会生成一个GTID事务号。
show binlog events in 'binlog.000001'\G;
对于事务块里有临时表的DDL语句,可以正常执行。
#开启GTID;
[mysqld]
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=mysql-bin
reset master;
mysql> drop table t;
Query OK, 0 rows affected (1.49 sec)
mysql> show master status\G
*************************** 1. row ***************************
File: binlog.000001
Position: 360
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: fa68231f-8d1b-11ef-a4d3-fa163e2f8777:1
1 row in set (0.00 sec)
#没有生成事务ID;
begin;
create temporary table tmp(a int ,b date);
insert into tmp values(10,'2025-05-20');
commit;
mysql> show binlog events in 'binlog.000001';
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| binlog.000001 | 4 | Format_desc | 1 | 126 | Server ver: 8.0.28, Binlog ver: 4 |
| binlog.000001 | 126 | Previous_gtids | 1 | 157 | |
| binlog.000001 | 157 | Gtid | 1 | 234 | SET @@SESSION.GTID_NEXT= 'fa68231f-8d1b-11ef-a4d3-fa163e2f8777:1' |
| binlog.000001 | 234 | Query | 1 | 360 | use `test`; DROP TABLE `t` /* generated by server */ /* xid=318 */ |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
4 rows in set (0.01 sec)
#DROP TABLE 产生一个GTID;创建临时表的事务并没有生成GTID;
mysql> create table t2(id int);
Query OK, 0 rows affected (2.67 sec)
mysql> show binlog events in 'binlog.000001';
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| binlog.000001 | 4 | Format_desc | 1 | 126 | Server ver: 8.0.28, Binlog ver: 4 |
| binlog.000001 | 126 | Previous_gtids | 1 | 157 | |
| binlog.000001 | 157 | Gtid | 1 | 234 | SET @@SESSION.GTID_NEXT= 'fa68231f-8d1b-11ef-a4d3-fa163e2f8777:1' |
| binlog.000001 | 234 | Query | 1 | 360 | use `test`; DROP TABLE `t` /* generated by server */ /* xid=318 */ |
| binlog.000001 | 360 | Gtid | 1 | 437 | SET @@SESSION.GTID_NEXT= 'fa68231f-8d1b-11ef-a4d3-fa163e2f8777:2' |
| binlog.000001 | 437 | Query | 1 | 548 | use `test`; create table t2(id int) /* xid=567 */ |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
6 rows in set (0.00 sec)
创建临时表的事务没有生成GTID;#create temporary table temp1 也不会生成GTID;