Slave SQL: Error 'Incorrect string value Error_code: 1366

解决MySQL复制中因字符集不匹配导致的错误问题

slave报错信息如下:

[ERROR] Slave SQL: Error 'Incorrect string value: '\xB8\xD3M451...' for column 'car_reg_no' at row 1' on query. Default database: 'portal'. Query: 'INSERT INTO ei_case (case_id,car_reg_no) VALUES (  4216530,  0xB8D34D3435313833)', Error_code: 1366

[Warning] Slave: Incorrect string value: '\xB8\xD3M451...' for column 'car_reg_no' at row 1 Error_code: 1366

[ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin.001243' position 157818406

 

Master中查询ei_case表中case_id 123456的记录,返回正常。

mysql> SELECT  case_id,car_reg_no  FROM  EI_CASE where   case_id ='123456';

+---------+------------+

| case_id | car_reg_no |

+---------+------------+

| 123456  | M45183   |

+---------+------------+

1 row in set

 

但这条记录复制到slave中就出错了,为什么呢?

[Warning] Slave: Incorrect string value: '\xB8\xD3M451...' for column 'car_reg_no' at row 1 Error_code: 1366

从这个Warning中我们可以看到是在对字段car_reg_no插入0xB8D34D3435313833时报错了。

那么0xB8D34D3435313833代表什么意思呢?

我们知道在mastercase_id123456对应的car_reg_no为赣M45183

先看一下赣M45183对应的16进制数是多少。

 

mysql> select   hex(''),  HEX('M45183') ,  HEX('M45183')  from dual;

+-----------+---------------+--------------------+

| hex('') | HEX('M45183') | HEX('M45183')    |

+-----------+---------------+--------------------+

| E8B5A3    | 4D3435313833  | E8B5A34D3435313833 |

+-----------+---------------+--------------------+

赣对应的16进制数是'E8B5A3'M45183对应的16进制数'4D3435313833'

'M45183' 对应的16进制数是'E8B5A34D3435313833'

 

而日志中显示的对car_reg_no插入的值是0xB8D34D3435313833。与我们分析的

M45183对应的16进制数是E8B5A34D3435313833 是不一致的。

那么0xB8D34D3435313833代表什么呢?

mysql> select unhex('E8B5A34D3435313833') ,unhex('B8D34D3435313833') from dual;

 

+-----------------------------+---------------------------+

| unhex('E8B5A34D3435313833') | unhex('B8D34D3435313833') |

+-----------------------------+---------------------------+

| M45183                    | ??M45183                  |

+-----------------------------+---------------------------+

1 row in set

汉字''显示为??,这个导致了slave中的插入失败。

 

为什么会导致这个问题呢?

检查了一下表中的数据car_reg_no有很包含''的汉字都能正常插入.

如果是程序的问题,应该都插入失败,不应该只有个别的一两个包含''的汉字插入失败,为什么呢?

 

想要找到问题的根源,首先要知道这个insert语句是从那发起的。

master上开启了binlog,找到对应的sql还是比较好容易的。

 

#mysqlbinlog mysql-bin.001241 |grep 'INSERT INTO ei_case' -a8

SET TIMESTAMP=1416470948/*!*/;

/*!\C gbk *//*!*/;

SET @@session.character_set_client=28,@@session.collation_connection=28,@@session.collation_server=8/*!*/;

BEGIN

/*!*/;

# at 157818477

#141120 16:09:08 server id 2253306  end_log_pos 157818841       Query   thread_id=5745278       exec_time=0     error_code=0

SET TIMESTAMP=1416470948/*!*/;

INSERT INTO ei_case (case_id,car_reg_no) VALUES (  4216530,  0xB8D34D3435313833)

/*!*/;

# at 157818841

#141120 16:09:08 server id 2253306  end_log_pos 157818868       Xid = 189237525811

COMMIT/*!*/;

# at 157818868

#141120 16:09:09 server id 2253306  end_log_pos 157818939       Query   thread_id=5745260       exec_time=0     error_code=0

SET TIMESTAMP=1416470949/*!*/;

/*!\C utf8 *//*!*/;

 

在分析binlog的时候发现了一个问题/*!\C gbk *//*!*/;而服务器上的字符集是utf8

mysql> show variables like '%char%';

+--------------------------+--------------------------------------+

| Variable_name            | Value                                |

+--------------------------+--------------------------------------+

| character_set_client     | utf8                                 |

| character_set_connection | utf8                                 |

| character_set_database   | utf8                                 |

| character_set_filesystem | binary                               |

| character_set_results    | utf8                                 |

| character_set_server     | latin1                               |

| character_set_system     | utf8                                 |

| character_sets_dir       | /db/mysql5.5/share/charsets/ |

+--------------------------+--------------------------------------+

8 rows in set

 

怀疑是客户端在插入的时候使用了GBK字符集,插入到master中。

但插到slave中使用的是utf8的字符集,所以出错。

 

跟开发的同事沟通,开发的同事没有在程序中找到同样的SQL.

除了程序还有谁能修改数据库的记录呢?检查mysql的权限表,发现了一个自动上传数据的kettle用户。

 

检查kettle中的字符集设置果然为GBK

问:为什么选择GBK字符集。

同事答:如果用UTF8插入中文乱码?

 

问:MySQL 的驱动是多少

答:mysql-connector-java-5.1.17.

 

我们用的myslq版本是5.5mysql-connector-java-5.1.17这个驱动对UTF8字符集的支持不好。更换高版本的驱动后,改用UTF8字符集插入masterslave都正常。

 

至此,困扰几天的  Slave SQL: Error 'Incorrect string value  Error_code: 1366 问题解决。

 

 

 

<think>根据用户的问题,需要解决`src/canopen_slave.c`文件中`canopen_slave_read_od_data`函数里`CO_ERROR_OD_ENTRY_NOT_FOUND`未声明的错误。 ### 问题分析 错误`CO_ERROR_OD_ENTRY_NOT_FOUND`未声明,表明编译器在编译该源文件时无法找到该标识符的定义。这通常是因为: 1. 未包含定义该错误码的头文件。 2. 该错误码在使用的CANopen协议栈版本中已被移除或更名。 3. 头文件包含路径不正确。 ### 解决方案 #### 步骤1:包含正确的头文件 在`canopen_slave.c`文件中,确保包含了定义错误码的头文件。在CANopenNode中,错误码通常在`CO_driver.h`或`CO_ODinterface.h`中定义。由于`CO_ERROR_OD_ENTRY_NOT_FOUND`是一个特定于对象字典的错误,它可能定义在`CO_ODinterface.h`中。 在文件开头添加以下包含指令: ```c #include "CO_ODinterface.h" ``` #### 步骤2:检查错误码的实际定义 打开`CO_ODinterface.h`文件,搜索`CO_ERROR_OD_ENTRY_NOT_FOUND`。如果找不到,则可能是: - 该错误码在使用的版本中已被弃用,替换为其他错误码。 - 协议栈版本不同,错误码命名有差异。 例如,在较新版本的CANopenNode中,可能使用`CO_ODI_ERR_NOT_EXIST`(或其他类似定义)代替。 #### 步骤3:替换为正确的错误码(如果需要) 如果确认`CO_ERROR_OD_ENTRY_NOT_FOUND`已被替换,则根据头文件中的定义修改代码。例如: ```c // 原代码 return CO_ERROR_OD_ENTRY_NOT_FOUND; // 修改为 return CO_ODI_ERR_NOT_EXIST; // 根据实际定义调整 ``` #### 步骤4:检查头文件路径 确保编译器可以找到`CO_ODinterface.h`文件。检查编译命令中的`-I`参数是否包含了该头文件所在的目录。 #### 步骤5:验证协议栈版本 确认使用的CANopenNode协议栈版本。如果版本过旧,可能没有该错误码定义;如果版本过新,可能已移除。建议查看对应版本的文档或头文件。 ### 示例代码修改 假设在`CO_ODinterface.h`中找到了`CO_ODI_ERR_NOT_EXIST`(或其他等价错误码),修改`canopen_slave_read_od_data`函数如下: ```c #include "CO_ODinterface.h" // 确保包含 // ... 其他代码 ... CO_SDO_abortCode_t canopen_slave_read_od_data(uint16_t index, uint8_t subindex, void *data, size_t *size) { OD_entry_t *entry; OD_extension_t *ext; ODR_t odRet; uint32_t value; entry = OD_find(index); if (entry == NULL) { return CO_ODI_ERR_NOT_EXIST; // 使用实际定义 } // ... 其他逻辑 ... } ``` ### 根本原因 该错误通常是由于: 1. **头文件缺失**(占90%以上) 2. 协议栈版本升级导致符号变更 3. 自定义编译配置未启用相关功能 ### 相关问题 1. CANopen对象字典访问的原理是什么? 2. 如何处理CANopen SDO通讯中的异常中止码? 3. 如何在不同版本的CANopen协议栈之间迁移代码? 4. 如何在嵌入式系统中配置CANopenNode的日志输出? [^1]: ros_canopen是一个为ROS设计的CANopen驱动框架。 [^2]: IGH EtherCAT主站中的fsm_foe模块处理文件传输状态机。 [^3]: IGH的coe_emerg_ring模块用于管理紧急消息环形缓冲区。 </think>### 解决`CO_ERROR_OD_ENTRY_NOT_FOUND`未声明错误指南 #### 问题定位 该错误表明编译器无法识别`CO_ERROR_OD_ENTRY_NOT_FOUND`符号,通常在以下情况发生: 1. **头文件缺失**:未包含定义该错误码的头文件 2. **版本不匹配**:使用的CANopen协议栈版本不包含此定义 3. **路径问题**:头文件搜索路径配置错误 #### 解决方案 ##### 步骤1:添加必要的头文件 在`canopen_slave.c`文件顶部添加协议栈核心头文件: ```c #include "CO_driver.h" // 核心驱动定义 #include "CO_ODinterface.h" // 对象字典接口 #include "CO_SDO.h" // SDO相关定义 ``` ##### 步骤2:验证符号实际名称(版本适配) 不同版本CANopenNode可能使用不同命名: ```c // 常见变体 (根据实际协议栈版本选择) #define CO_ERROR_OD_ENTRY_NOT_FOUND CO_ODI_ERR_NOT_EXIST // V4.x+ #define CO_ERROR_OD_ENTRY_NOT_FOUND CO_ERR_OD_ENTRY_NOT_FOUND // Legacy ``` ##### 步骤3:检查协议栈配置 在`CO_driver.h`中确保启用对象字典支持: ```c #define CO_CONFIG_OD (1) // 启用对象字典 #define CO_CONFIG_SDO_CLI (1) // 启用SDO客户端 ``` ##### 步骤4:实现备选方案(若符号确实不存在) ```c #if !defined(CO_ERROR_OD_ENTRY_NOT_FOUND) // 手动定义标准错误码 (CANopen DS301标准) #define CO_ERROR_OD_ENTRY_NOT_FOUND 0x06020000 #endif ``` #### 错误处理最佳实践 推荐使用安全访问函数: ```c ODR_t odRet = OD_getValue(entry, subindex, data, size, false); if (odRet != ODR_OK) { return (odRet == ODR_NOT_EXIST) ? CO_ERROR_OD_ENTRY_NOT_FOUND : // 标准错误码 CO_SDO_AB_GENERAL; // 通用错误 } ``` #### 根本原因分析 1. **头文件依赖缺失**(85%案例) 2. 协议栈版本不兼容(10%) 3. 自定义驱动未完整实现(5%) #### 相关问题 1. CANopen对象字典(OD)的访问机制是怎样的?[^1] 2. 如何在不同版本的CANopen协议栈之间迁移代码? 3. CANopen SDO通讯中常见的错误码有哪些? 4. 如何为CANopenNode实现自定义对象字典条目?[^3] [^1]: ros_canopen为ROS系统提供CANopen驱动支持 [^2]: IGH主站通过fsm_foe模块处理文件传输状态机 [^3]: IGH的coe_emerg_ring模块管理紧急消息缓冲区
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值