MySQL replication illegal mix of collations
MySQL replication case 一则
转载:http://www.vmcd.org/2013/09/mysql-replication-case-%E4%B8%80%E5%88%99/
Posted by admin on September 10th, 2013
最近同事处理了一则mysql复制错误.发出来参考下
MYSQL同步出错,报错信息如下:
Last_Errno: 1267 Last_Error: Error 'Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'concat'' on query. Default database: 'inshop_app'. Query: 'INSERT INTO inshop_app.app_sms_order_info (ORDER_CODE, ORDER_TIME, ORDER_AMOUNT, ORDER_CONTENT, BUY_NUM, ORDER_STATUS, MERCHANT_ID, CREATE_TIME, UPDATE_TIME, APP_TYPE, pay_time, remark) VALUES( NAME_CONST('my_order_code',_utf8'SBY130830010708_F0' COLLATE 'utf8_general_ci'),NOW(),'0','1次', NAME_CONST('my_sms_num',1125000),'1', NAME_CONST('my_merchant_id',10708),NOW(),NOW(),'2',NOW(),CONCAT ('钻展赠送:', NAME_CONST('my_sms_num',1125000)))' |
出错原因分析:
此SQL在Master上执行时是这样的
INSERT INTO inshop_app.app_sms_order_info (ORDER_CODE, ORDER_TIME, ORDER_AMOUNT, ORDER_CONTENT, BUY_NUM, ORDER_STATUS, MERCHANT_ID, CREATE_TIME, UPDATE_TIME, APP_TYPE, pay_time, remark) VALUES( 'SBY130830010708_F0',NOW(),'0','1次', 1125000,'1', 10708,NOW(),NOW(),'2',NOW(),CONCAT ('钻展赠送:', 1125000)) |
该SQL本身是没问题的,执行成功,但是MYSQL在记录BINLOG的时候,会对常量用NAME_CONST()函数进行“标识”
同步的报错就出现在这个地方
CONCAT ('钻展赠送:', NAME_CONST('my_sms_num',1125000)) |
其中,’钻展赠送:’是UTF8字符集,NAME_CONST(‘my_sms_num’,1125000)得到的数值型常量被自动转型为LATIN1字符集,外层的CONCAT()函数不支持二种不同字符集进行连接,于是报错
以下测试可验证此分析:
无NAME_CONST()函数标识常量时,即如同在Master上执行时,成功
09:29:06 inshop_app> select concat('钻展赠送',123); +----------------------------+ | concat('钻展赠送',123) | +----------------------------+ | 钻展赠送123 | +----------------------------+ 1 row in set (0.00 sec) |
有NAME_CONST()函数标识常量时,即如同在Slave上执行时,失败
09:25:17 inshop_app> select concat('钻展赠送',name_const('colname',123)); ERROR 1267 (HY000): Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'concat' |
报错与同步是一样的错误
什么情况下MySQL会自动加上NAME_CONST函数
测试1: 直接insert
11:27:32 test> insert into lengzhenguo_mha(c3,c4) values(1,'a'),('2','b'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 |
BINLOG中的内容
#130909 11:28:35 server id 2009 end_log_pos 469 Query thread_id=10 exec_time=0 error_code=0 SET TIMESTAMP=1378697315/*!*/; insert into lengzhenguo_mha(c3,c4) values(1,'a'),('2','b') /*!*/; |
测试2: 简单的存储过程
13:16:42 test> create procedure p_test() -> begin -> insert into lengzhenguo_mha(c3,c4) values(10,'abc'),('20','xyz'); -> commit; -> end -> $ Query OK, 0 rows affected (0.00 sec) 13:17:38 test> call p_test(); Query OK, 0 rows affected (0.00 sec) |
BINLOG中的内容
#130909 13:18:21 server id 2009 end_log_pos 328 Query thread_id=12 exec_time=0 error_code=0 use `test`/*!*/; SET TIMESTAMP=1378703901/*!*/; insert into lengzhenguo_mha(c3,c4) values(10,'abc'),('20','xyz') /*!*/; |
测试3:带参数的存储过程 类似bind value
13:22:43 test> CREATE procedure p_test_2 (i bigint, j varchar(30)) -> begin -> insert into lengzhenguo_mha(c3,c4) values(i,j); -> commit; -> end -> $ Query OK, 0 rows affected (0.00 sec) 13:23:16 test> call p_test_2(100,'dba'); Query OK, 0 rows affected (0.00 sec) 13:25:10 test> call p_test_2('500','dba'); Query OK, 0 rows affected (0.00 sec) |
BINLOG中的内容
#130909 13:23:32 server id 2009 end_log_pos 612 Query thread_id=12 exec_time=0 error_code=0
SET TIMESTAMP=1378704212/*!*/; insert into lengzhenguo_mha(c3,c4) values( NAME_CONST('i',100), NAME_CONST('j',_latin1'dba' COLLATE 'latin1_swedish_ci')) /*!*/; #130909 13:25:15 server id 2009 end_log_pos 1226 Query thread_id=12 exec_time=0 error_code=0 SET TIMESTAMP=1378704315/*!*/; insert into lengzhenguo_mha(c3,c4) values( NAME_CONST('i',500), NAME_CONST('j',_latin1'dba' COLLATE 'latin1_swedish_ci')) /*!*/; |
注意:’500′在写入Binlog时,已经被转换成数值型了
目前已知的解决方法:
方法1:不要直接使用数值,直接给予字符串,建议使用此方法
09:25:27 inshop_app> select concat('钻展赠送',name_const('colname','123')); +----------------------------------------------------+ | concat('钻展赠送',name_const('colname','123')) | +----------------------------------------------------+ | 钻展赠送123 | +----------------------------------------------------+ 1 row in set (0.00 sec) |
注意:这里的123加引号,字符串~
方法2:先进行类型转换
09:56:32 inshop_app> select concat('钻展赠送',convert(name_const('colname',123) using utf8)); +----------------------------------------------------------------------+ | concat('钻展赠送',convert(name_const('colname',123) using utf8)) | +----------------------------------------------------------------------+ | 钻展赠送123 | +----------------------------------------------------------------------+ 1 row in set (0.00 sec) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构