【问题标题】:JDBC issues SET NAMES utf8 causes Illegal mix of collationsJDBC 问题 SET NAMES utf8 导致非法混合排序规则
【发布时间】:2018-02-17 08:13:32
【问题描述】:

今天,一位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 服务器。两台服务器的字符集和排序规则配置相同。

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

【问题讨论】:

  • mysql中也有正常设置“utf8”的连接字符串。

标签: java mysql spring mybatis


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2014-03-06
    • 1970-01-01
    • 2012-08-28
    • 2020-04-24
    • 2013-01-02
    • 2011-01-20
    • 2013-08-01
    • 2019-09-14
    • 1970-01-01
    相关资源
    最近更新 更多