记一次阿里云RDS执行DDL语句异常的问题
原创2021/9/1大约 2 分钟
记一次阿里云RDS执行DDL语句异常的问题
1、业务背景
现有某 Spring Boot + MyBatis 的项目,在 Mapper.xml 文件中,使用到了 DDL 建表语句,如下:
CREATE TABLE b
(
SELECT * FROM a WHERE 1 = 2
);2、问题现象
在本地和测试环境下,执行都没问题,MySQL 版本为 5.7,引擎当然为 Innodb,但上生产之后执行报错,生产环境为阿里云的 RDS-MySQL 5.7,报错的堆栈信息如下:
org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.sql.SQLException: Statement violates GTID consistency: CREATE TABLE ... SELECT.
### The error may exist in URL [jar:file:/xxx/xxx.jar!/BOOT-INF/classes!/xxx/XxxMapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: CREATE TABLE `b` (SELECT * FROM a WHERE 1 = 2 );
### Cause: java.sql.SQLException: Statement violates GTID consistency: CREATE TABLE ... SELECT.
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:199)
······3、定位原因
深层原因不详,但根据异常的字面意思不难看出是“语句违反 GTID 一致性”,百度、Google 之后,很多文章说让修改 MySQL 的配置文件的 gtid_mode 和 enforce_gtid_consistency 选项,但是在阿里云 RDS 控制台并没有对应的参数配置,从阿里云售后技术处获悉:阿里云的 RDS-MySQL 涉及到主从同步,默认使用的是 GTID 方式,不能做对应配置的修改。
4、解决方案
改写 SQL 语句如下:
-- 这会将表 a 的完整字段结构(不含数据)和索引复制一份生成表 b
create table b like a;
-- 把a表里的数据复制到b表里面
insert into b select * from a;已上就约等于:
create table b select * from a;为什么是约等于?因为下面这种复制不会复制主键、索引等内容,而且select可以自定义一些字段复制,注意他们的区别

