zoukankan      html  css  js  c++  java
  • Slave SQL: Error 'Incorrect string value ... Error_code: 1366

    背景:

    主从环境一样,字符集是utf8。

    Slave复制报错,平时复制都正常也没有出现过问题,今天突然报错:

    150610 17:47:10 [ERROR] Slave SQL: Error 'Incorrect string value: 'xD3xC3xB6xD2xBBxBB...' for column 'remark' at row 1' on query. Default database: 'jj'. Query: 'INSERT INTO user_book(appType,bookId,createTime,deviceType,id,modifyTime,money,remark,status,userId) VALUES (1,8004453,'2015-06-10 17:06:10',0,0,'2015-06-10 17:06:10',600,0xCAB9D3C3B6D2BBBBC2EB20454E4547435056505452555020B9BAC2F2,1,4669278)', Error_code: 1366
    150610 17:47:10 [Warning] Slave: Incorrect string value: 'xD3xC3xB6xD2xBBxBB...' for column 'remark' at row 1 Error_code: 1366
    150610 17:47:10 [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-3306.003582' position 207897687

    perror 1366

    MySQL error code 1366 (ER_TRUNCATED_WRONG_VALUE_FOR_FIELD): Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld

    从上面2个信息得到从库复制失败的原因是因为字符集的问题引起的。

    分析:

    在Master上查询该条记录,看看是否正常:

    >select remark from user_book where appType=1 and bookId=8004453 and createTime='2015-06-10 17:06:10';
    +-------------------------------------+
    | remark                              |
    +-------------------------------------+
    | 使用兑换码 ENEGCPVPTRUP 购买        |
    +-------------------------------------+

    在主上写入正常,但在从上写入就报错了,为什么?

     [Warning] Slave: Incorrect string value: 'xD3xC3xB6xD2xBBxBB...' for column 'remark' at row 1 Error_code: 1366

    在错误日志里面看到从上对应插入的语句是:

    INSERT INTO user_book(appType,bookId,createTime,deviceType,id,modifyTime,money,remark,status,userId) VALUES (1,8004453,'2015-06-10 17:06:10',0,0,'2015-06-10 17:06:10',600,0xCAB9D3C3B6D2BBBBC2EB20454E4547435056505452555020B9BAC2F2,1,4669278)

    这里的"0xCAB9D3C3B6D2BBBBC2EB20454E4547435056505452555020B9BAC2F2"代表什么意思呢?因为在主上看到的值是"使用兑换码 ENEGCPVPTRUP 购买"。那么看下他的16进制数是多少:

    主:
    >select hex('使用兑换码'),hex('ENEGCPVPTRUP'),hex('购买'),hex('使用兑换码 ENEGCPVPTRUP 购买')
        -> ;
    +--------------------------------+--------------------------+---------------+------------------------------------------------------------------------+
    | hex('使用兑换码')              | hex('ENEGCPVPTRUP')      | hex('购买')   | hex('使用兑换码 ENEGCPVPTRUP 购买')                                    |
    +--------------------------------+--------------------------+---------------+------------------------------------------------------------------------+
    | E4BDBFE794A8E58591E68DA2E7A081 | 454E45474350565054525550 | E8B4ADE4B9B0  | E4BDBFE794A8E58591E68DA2E7A08120454E4547435056505452555020E8B4ADE4B9B0 |
    +--------------------------------+--------------------------+---------------+------------------------------------------------------------------------+

    看到主上的值转换出来之后和从上的不一致,这个就是这次问题的所在,那么通过unhex来看看从上的到底是什么导致插入错误的。

    主:E4BDBFE794A8E58591E68DA2E7A08120 454E4547435056505452555020 E8B4ADE4B9B0
    从:CAB9D3C3B6D2BBBBC2EB20 454E4547435056505452555020 B9BAC2F2

    上面看到对于英文是没有问题的,字符集问题主要出在汉字上面。通过unhex查看:

    主:
    >select unhex('E4BDBFE794A8E58591E68DA2E7A08120'),unhex('454E4547435056505452555020'),unhex('E8B4ADE4B9B0');
    +-------------------------------------------+-------------------------------------+-----------------------+
    | unhex('E4BDBFE794A8E58591E68DA2E7A08120') | unhex('454E4547435056505452555020') | unhex('E8B4ADE4B9B0') |
    +-------------------------------------------+-------------------------------------+-----------------------+
    | 使用兑换码                                | ENEGCPVPTRUP                        | 购买                  |
    +-------------------------------------------+-------------------------------------+-----------------------+
    
    从:
    >select unhex('CAB9D3C3B6D2BBBBC2EB20'),unhex('454E4547435056505452555020'),unhex('B9BAC2F2');
    +---------------------------------+-------------------------------------+-------------------+
    | unhex('CAB9D3C3B6D2BBBBC2EB20') | unhex('454E4547435056505452555020') | unhex('B9BAC2F2') |
    +---------------------------------+-------------------------------------+-------------------+
    | ʹ?öһ???                             | ENEGCPVPTRUP                        | ????                  |
    +---------------------------------+-------------------------------------+-------------------+

    上面得出的结果是确实存在乱码导致插入异常。理论上来说主上执行什么,从上就应该执行什么,不会出现问题,那这次错误是怎么回事?

    主从上表结构都是一样的,主从表的remark字段的字符集是utf8,并且从在MySQL客户端上也可以正常插入中文,为什么通过复制存就出问题了?所以乱码和表字符集没有关系。如果是程序问题,那主从应该都会出错。所以和程序也没有关系,那到底和什么有关系?

    在主上的binlog查看那条插入语句:

    /*!C gbk *//*!*/;
    SET @@session.character_set_client=28,@@session.collation_connection=28,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    BEGIN
    /*!*/;
    # at 207897755
    #150610 17:06:10 server id 3  end_log_pos 207897783     Intvar  
    SET INSERT_ID=47282/*!*/;
    # at 207897783
    #150610 17:06:10 server id 3  end_log_pos 207898096     Query   thread_id=3945271       exec_time=0     error_code=0
    use `jj`/*!*/;
    SET TIMESTAMP=1433927170/*!*/;
    INSERT INTO user_book(appType,bookId,createTime,deviceType,id,modifyTime,money,remark,status,userId) VALUES (1,8004453,'2015-06-10 17:06:10',0,0,'2015-06-10 17:06:10',600,0xCAB9D3C3B6D2BBBBC2EB20454E4547435056505452555020B9BAC2F2,1,4669278)
    /*!*/;

    这里需要注意:在上面红色加粗的地方看到插入的时候默认字符集是gbk,而整个数据库的字符集也是gbk,程序客户端写入也是gbk。但是数据表的remark字段的字符集是utf8的。在主的写入时,utf8可以包含gbk的编码,进行内部转换,所以主写入是没有问题的。但是从库的SQL线程在执行时候就报错,说明问题可以定位到从库在执行的时候报错。

    说到这里,有个问题是为什么binlog记录的是十六进制,而不是正常的?问题就出在这里,具体的分析见:http://backend.blog.163.com/blog/static/20229412620133274030845/

    那为什么之前复制没有问题,而现在复制出现了问题。原因是之前这个字段的写入都是非中文的字符串,现在有中文写入,错误就来了。

    解决:

    把没有写入的数据补到从上去,并且把主从数据库表的remark字段都设置成gbk,问题解决。另一个方法就是把binlog format设置成Row。

    总结:

    上面的问题说明,对MySQL进行操作的时候一定要注意字符集编码的问题,最好让客户端、服务端、表、字段的字符集保持一致。不一致导致的乱码问题是比较常见的一种错误。

    相关文章

    http://blog.csdn.net/lwei_998/article/details/41346655

    http://www.cnblogs.com/zhoujinyi/archive/2012/11/01/2748313.html

  • 相关阅读:
    Mac之雕虫小技
    Python 合并两个字典(Dictionary)中相同key的value的方法
    linux只保留最新n个文件
    自动化测试笔记
    python实现一个判断时间的装饰,并抛出自定义异常
    python在字典列表中计算具有特定键的元素
    canvas游戏
    教为学:Oracle 11g OCP之路(七):数据结构
    教为学:Oracle 11g OCP之路(八):用户权限管理
    ADO.NET入门教程(六) 谈谈Command对象与数据检索
  • 原文地址:https://www.cnblogs.com/zhoujinyi/p/4568663.html
Copyright © 2011-2022 走看看