今天,一位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,collate是utf8_general_ci,列名称的字符集是utf8mb4,collate是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和collation配置。
更新: 我重新启动MySQL服务器后,问题就消失了! Connector J或MySQL服务器中可能存在错误,因为文档中说character_set_server和collation-server是动态选项,但实际上并非所有客户端都适用:它适用于本机mysql客户端但不适用于Connector J。
答案 0 :(得分:0)
更新: 如文档所述,character_set_server选项不是动态的,但您可以通过将connectionCollation = utf8mb4_unicode_ci添加到jdbc配置字符串或者只是重新启动MySQL服务器来解决这个问题,这在所有情况下都是不可接受的。