JDBC问题SET NAMES utf8导致非法混合排序

时间:2017-09-08 11:50:09

标签: java mysql spring mybatis

今天,一位java工程师来找我,并向我显示错误:

select * from some_table where name=? ...
### Cause: java.sql.SQLException: Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='

默认字符集是utf8,collat​​e是utf8_general_ci,列名称的字符集是utf8mb4,collat​​e是utf8mb4_unicode_ci,列'name'的值是utf8mb4值(包括表情符号)。

所以我检查了数据库配置并找到了:

character_set_client=utf8
character_set_connection=utf8
character_set_server=utf8

所以,我认为修复此错误很容易:

set global character_set_server=utf8mb4;
set global collation_server=utf8mb4_unicode_ci;
set global init_connect='SET NAMES utf8mb4'

但重启java程序后,错误仍然存​​在! 所以我启用了MySQL服务器中的常规日志,发现了非常奇怪的SQL语句:

4584243 Connect some_user@10.17.1.100 on some_database
4584243 Query   SET NAMES utf8mb4     # this is the result for the init_connect.
Query   /* mysql-connector-java-5.1.35 ( Revision: 
5fb9c5849535c13917c2cf9baaece6ef9693ef27 ) */SHOW VARIABLES WHERE 
Variable_name ='language' OR Variable_name = 'net_write_timeout' OR 
Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR 
Variable_name = 'character_set_client' OR Variable_name = 
'character_set_connection' OR Variable_name = 'character_set' OR 
Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR 
Variable_name = 'transaction_isolation' OR Variable_name = 
'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 
'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 
'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR 
Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR 
Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR 
Variable_name = 'license' OR Variable_name = 'init_connect'
4584243 Query   /* mysql-connector-java-5.1.35 ( Revision: 
5fb9c5849535c13917c2cf9baaece6ef9693ef27 ) */SELECT 
 @@session.auto_increment_increment
4584243 Query   SELECT @@session.autocommit
4584243 Query   SET NAMES utf8       # Who issued this?
4584243 Query   SET character_set_results = NULL
4584243 Query   SET autocommit=1
4584243 Query   select @@session.tx_read_only
4584243 Query   SELECT @@session.tx_isolation
4584243 Query   select  *  from  some_table where name = 'xxxx'  # OK, now normal business SQL statement starts 

可以清楚地看到有一个SQL:

4584243 Query   SET NAMES utf8       # JDBC issued this

此SQL导致我的修复失效。谁或什么框架会发出这种SQL,如何禁用它?

欢迎任何建议。

更新: 我认为这不是JDBC,但是MySQL服务器导致了这个问题,因为当我使用原生JDBC连接到另一个服务器并使用init_connect ='set names utf8mb4'时,客户端连接的字符集正确地设置为utf8mb4,我不知道为什么它不能用于这个MySQL服务器。两个服务器都具有相同的charset和collat​​ion配置。

更新: 我重新启动MySQL服务器后,问题就消失了! Connector J或MySQL服务器中可能存在错误,因为文档中说character_set_server和collat​​ion-server是动态选项,但实际上并非所有客户端都适用:它适用于本机mysql客户端但不适用于Connector J。

1 个答案:

答案 0 :(得分:0)

更新: 如文档所述,character_set_server选项不是动态的,但您可以通过将connectionCollat​​ion = utf8mb4_unicode_ci添加到jdbc配置字符串或者只是重新启动MySQL服务器来解决这个问题,这在所有情况下都是不可接受的。