mysqlclient 连 MariaDB 报 Illegal mix of collations:初始化覆盖了排序规则
mysqlclient 连接 MariaDB 后出现 Illegal mix of collations,先在实际会话核对字符集和 collation。区分 2.1 初始化覆盖与 2.2.0 起的 collation 参数,保留原有表结构。
应用用 mysqlclient 连接 MariaDB,表列已经是 utf8mb4_unicode_ci,比较 CAST 结果时却报 Illegal mix of collations,另一侧显示 utf8mb4_general_ci。先核对实际业务连接的 collation_connection,再查看驱动初始化顺序。服务器默认值、表列与连接会话不是同一份设置。
mysqlclient 2.1 的字符集初始化可能在 init_command 后再次发送 SET NAMES,从而覆盖前面指定的排序规则。mysqlclient 从 2.2.0 起提供 collation 连接参数;不要把“无法指定排序规则”的旧版本问题当作当前所有版本的限制。
两边都是 utf8mb4,仍可能按不同规则比较
保留完整错误、实际 SQL、mysqlclient 和 MariaDB 版本,以及驱动连接参数。先判断涉及的是两个表列,还是一个表列与 CAST、文字或其他表达式。若错误来自两个已定义列,连接参数不一定能修复其规则差异。
在执行失败查询的同一连接上只读查看:
SELECT VERSION(), DATABASE(),
@@SESSION.character_set_client,
@@SESSION.character_set_connection,
@@SESSION.character_set_results,
@@SESSION.collation_connection;
用现有表定义核对参与比较的列。另开一个管理窗口查询正常,不能证明连接池中的应用会话相同。服务器或数据库默认值也不证明已有列与现有会话都采用该规则。
字符集决定字符如何表示,排序规则决定比较与排序的方式。utf8mb4 的名称相同,不代表 utf8mb4_unicode_ci 与 utf8mb4_general_ci 可以在所有表达式中直接混用。当前 MariaDB 的默认规则还随版本变化,不能把旧版的 general_ci 写成永远固定的默认值。
检查 SET NAMES 谁最后执行
SET NAMES 会设置 character_set_client、character_set_connection、character_set_results,并相应设置 collation_connection。省略 COLLATE 时采用该字符集的默认规则,未必是你在服务器配置里选择的规则。
如果连接日志先出现带 COLLATE 的 SET NAMES,后面又出现不带 COLLATE 的 SET NAMES,应以最后实际会话值判断。init_command 或服务端 init_connect 写得正确,也可能在后续初始化中被覆盖。不要只重复添加同一条初始化语句。
日志可能包含业务数据,收集时限制范围并脱敏。没有查询日志时,至少在连接初始化全部完成后读取会话值,并核对项目实际驱动版本与创建连接的调用链。
受支持版本同时指定 charset 与 collation
使用支持该参数的 mysqlclient 时,将显式字符集和所需排序规则放在实际创建连接的位置。下面仅展示参数形式,凭据和地址继续从项目已有的受控配置读取:
import MySQLdb
connection = MySQLdb.connect(
**existing_connection_options,
charset="utf8mb4",
collation="utf8mb4_unicode_ci",
)
existing_connection_options 是项目已验证的连接字典,示例不会自动生成它。不要让这个字典同时包含重复的 charset 或 collation 键;保留原来的 TLS、用户、数据库、端口和其他选项。排序规则也需由当前服务器支持,并与实际比较语义一致,不能仅因为示例用了 unicode_ci 就替全项目选择它。
mysqlclient 2.2.0 已不支持 Python 3.7,后续版本还有各自的 Python 与客户端库要求。升级前核对项目兼容性,不为增加一个参数盲目覆盖锁文件。较旧版本不能直接传入尚不支持的 collation 参数。
无法立即升级时,可按该版本支持的连接生命周期,在字符集初始化完成之后,由受控的连接初始化代码明确设置所需规则。设置应覆盖每一条新建业务连接;框架创建或复用连接的入口不同,需要从它支持的配置方式接入。字符集与 collation 名称只能来自已验证的固定配置,不用外部输入拼接初始化 SQL。
只修连接分支,不先转换整库
若实际会话已符合预期,仍然报两个表列的规则冲突,应回到表达式与列定义检查。给表达式加 COLLATE 或迁移列规则都可能改变相等判断、排序、索引使用和唯一约束,需要按真实业务单独评估。
先保存连接配置与依赖版本,再安排受影响连接的更新。正在使用的连接应按正常生命周期排空,不随手终止业务事务。修改配置不会自动改变已经创建的会话,也不要求为了这一项重启整个数据库。
验收时,通过原来的应用查询路径检查新连接的 collation_connection,确认原比较不再报同一错误,结果与预期排序语义一致;还要覆盖后续新建连接,而不是只验证一个临时窗口。
需要回退时恢复本次连接参数和兼容依赖,按项目流程重建受影响连接。这个修复不转换历史数据,也不会自动纠正其他表列的既有规则;若排查中另做了结构迁移,必须按它自己的数据恢复方案处理。


