ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.

创建表时报错,如下:

mysql> create table t_idb_big as select * from information_schema.columns;
ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.
mysql>

错误原因:

这是因为在5.6及以上的版本内,开启了 enforce_gtid_consistency=true 功能导致的,MySQL官方解释说当启用 enforce_gtid_consistency 功能的时候,MySQL只允许能够保障事务安全,并且能够被日志记录的SQL语句被执行,像create table … select 和 create temporarytable语句,以及同时更新事务表和非事务表的SQL语句或事务都不允许执行。

解决方法:

方法一:
修改 :SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = off;
配置文件中 :ENFORCE_GTID_CONSISTENCY = off;
方法二(测试成功):
将 create table xxx as select 的方式拆分成两部分。
create table xxxx like data_mgr;
insert into xxxx select *from data_mgr;


1.当设置ENFORCE_GTID_CONSISTENCY = off时,错误消息说GTID_MODE = ON时需要ENFORCE_GTID_CONSISTENCY = ON,也就是需要设置GTID_MODE = OFF才能设置ENFORCE_GTID_CONSISTENCY = off
mysql> SET GLOBAL ENFORCE_GTID_CONSISTENCY = off;
ERROR 1779 (HY000): GTID_MODE = ON requires ENFORCE_GTID_CONSISTENCY = ON.
mysql> 

2.设置GTID_MODE = OFF
mysql> set global GTID_MODE = off;
ERROR 1788 (HY000): The value of @@GLOBAL.GTID_MODE can only be changed one step at a time: OFF <-> OFF_PERMISSIVE <-> ON_PERMISSIVE <-> ON. Also note that this value must be stepped up or down simultaneously on all servers. See the Manual for instructions.
mysql>
上面提示如果当前值为ON,要设置为OFF,则先设置为GTID_MODE=ON_PERMISSIVE,再设置GTID_MODE=OFF_PERMISSIVE,再设置GTID_MODE = off,如果将OFF设置为ON,则反过来设置即可。

继续设置:
mysql> set @@GLOBAL.GTID_MODE=ON_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)
mysql> set @@GLOBAL.GTID_MODE=OFF_PERMISSIVE;
ERROR 1766 (HY000): The system variable gtid_mode cannot be set when there is an ongoing transaction.

上面报错,当有正在进行的事务时,不能设置,所以就COMMIT一下:
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> set @@GLOBAL.GTID_MODE=OFF_PERMISSIVE;
Query OK, 0 rows affected (0.01 sec)

mysql> 
mysql> set @@GLOBAL.GTID_MODE=OFF;
Query OK, 0 rows affected (0.01 sec)

mysql> 
mysql> 
mysql> show variables like 'GTID_MODE';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| gtid_mode     | OFF   |
+---------------+-------+
1 row in set (0.00 sec)

mysql> 
3.然后再设置SET GLOBAL ENFORCE_GTID_CONSISTENCY = off:
mysql> SET GLOBAL ENFORCE_GTID_CONSISTENCY = off;
Query OK, 0 rows affected (0.00 sec)

mysql>
 

2019.11.07

<think>嗯,用户遇到了Java中的IllegalArgumentException异常,具体是Comparison method violates its general contract的错误。这个问题我之前在开发中碰到过,不过得仔细回想一下解决的方法。 首先,这个错误通常出现在自定义比较器的时候。用户可能在实现Comparator接口时,没有满足某些必要的条件,导致排序算法在运行时发现不一致的情况。比如,比较器没有遵循自反性、对称性或传递性这些规则。根据引用中的例子,比如在比较两个Interval对象时,只处理了start大于的情况,其他情况可能返回-1,但可能没有处理相等的情况,导致违反传递性。 接下来,我需要确定用户可能的错误场景。比如,比较器可能没有正确处理所有可能的输入情况。例如,当两个对象的start相等时,比较器应该返回0,而不是-1。否则,当两个对象相等时,比较结果可能不一致,导致排序算法崩溃。 然后,解决方案应该是检查比较器的实现,确保满足所有契约条件。可能需要添加更多的条件判断,覆盖所有情况,比如o1.start < o2.start返回-1,相等时返回0,否则返回1。同时,考虑使用Integer.compare()或者Comparator.comparingInt()来简化代码,避免手动处理比较逻辑,减少出错的可能。 另外,用户可能没有意识到在Java 7之后,比较器的实现要求更严格,尤其是在使用TimSort算法时,任何违反契约的行为都会抛出异常。而早期版本可能不会严格检查,导致问题在升级后出现。所以需要提醒用户检查Java版本,并确保比较逻辑的正确性。 可能还需要用户检查比较器中的逻辑是否有不一致的地方,比如多个条件判断之间是否有重叠或遗漏的情况。例如,如果同时比较多个字段,必须确保所有可能的组合都被正确处理,否则可能导致传递性失效。 最后,建议用户编写单元测试,覆盖各种边界情况,特别是相等、大小交替的情况,以验证比较器的正确性。同时,可以参考引用中的错误堆栈,定位到具体的代码行,检查该处的比较逻辑是否合理。 总结起来,解决步骤应该是:1. 检查比较器是否满足自反性、对称性、传递性;2. 使用内置方法简化比较逻辑;3. 处理所有可能的比较情况;4. 验证并测试比较器。</think>### 解决Java中`IllegalArgumentException: Comparison method violates its general contract`的方法 此错误是由于自定义比较器(`Comparator`)未满足以下三个数学契约条件导致的: 1. **自反性**:$a \text{ compare } a = 0$ 2. **对称性**:若$a \text{ compare } b > 0$,则$b \text{ compare } a < 0$ 3. **传递性**:若$a \text{ compare } b > 0$且$b \text{ compare } c > 0$,则$a \text{ compare } c > 0$ #### 分步解决方案 1. **检查比较逻辑是否覆盖所有情况** 例如,在区间排序问题中,若仅处理`o1.start > o2.start`返回1,其他情况返回-1,会导致`o1.start == o2.start`时违反对称性: ```java // 错误示例(引用[5]的代码) Collections.sort(intervals, new Comparator<Interval>() { @Override public int compare(Interval o1, Interval o2) { if (o1.start > o2.start) return 1; else return -1; // 未处理相等情况 } }); ``` **修复方法**: ```java if (o1.start != o2.start) { return Integer.compare(o1.start, o2.start); } else { return Integer.compare(o1.end, o2.end); // 添加次级排序条件 } ``` 2. **使用内置方法简化比较逻辑** 优先使用`Integer.compare(a, b)`或`Comparator.comparingInt()`,避免手动计算: ```java // 正确示例 Collections.sort(list, Comparator.comparingInt((Interval o) -> o.start) .thenComparingInt(o -> o.end)); ``` 3. **验证传递性** 对于复杂比较逻辑(如多字段排序),需确保所有可能的输入组合均满足传递性。例如: $$(a=1,b=2) \rightarrow 1,\ (b=2,c=3) \rightarrow 1,\ (a=1,c=3) \rightarrow 1$$ 4. **兼容Java 7+的严格检查** Java 7开始,`TimSort`算法会严格验证比较器的契约性[^1][^3],建议通过单元测试覆盖边界情况: ```java // 测试用例示例 @Test public void testComparator() { Interval a = new Interval(1, 2); Interval b = new Interval(1, 3); Interval c = new Interval(1, 2); Comparator<Interval> comp = new MyComparator(); assertTrue(comp.compare(a, b) < 0); assertTrue(comp.compare(b, a) > 0); assertEquals(0, comp.compare(a, c)); // 验证自反性 } ``` #### 常见错误场景及修复 | 场景描述 | 错误代码 | 修复代码 | |---------|---------|---------| | 未处理相等情况 | `if (a > b) return 1; else return -1;` | `return Integer.compare(a, b);` | | 多字段排序未定义优先级 | `return a.x - b.x + a.y - b.y;` | 分步比较:先`a.x`,再`a.y` |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值