Slave SQL: Error 'Incorrect string value ... Error_code: 1366

背景:

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

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

150610 17:47:10 [ERROR] Slave SQL: Error Incorrect string value: \xD3\xC3\xB6\xD2\xBB\xBB... for column remark at row 1 on query. Default database: jute. Query: INSERT INTO jute_file_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: \xD3\xC3\xB6\xD2\xBB\xBB... 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 jute_file_user_book where appType=1 and bookId=8004453 and createTime=2015-06-10 17:06:10;
+-------------------------------------+
| remark                              |
+-------------------------------------+
| 使用兑换码 ENEGCPVPTRUP 购买        |
+-------------------------------------+

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

 [Warning] Slave: Incorrect string value: \xD3\xC3\xB6\xD2\xBB\xBB... for column remark at row 1 Error_code: 1366

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

INSERT INTO jute_file_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                        | ????                  |
+---------------------------------+-------------------------------------+-------------------+

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

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

在主上的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 `jute`/*!*/;
SET TIMESTAMP=1433927170/*!*/;
INSERT INTO jute_file_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。但是数据库默认的字符集我是设置成utf8的。虽然数据库级别的字符集是utf8,但是程序连主库是使用gbk的,所以主的写入是没有问题的。但是从库的SQL线程会使用默认的字符集,即数据库默认字符集utf8。最终问题定位到:

在主上使用GBK编码写入,在从上使用UTF8编码写入。

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

解决:

把没有写入的数据补到从上去,并且把从的数据库默认字符集改成gbk,重启。

 

相关文章

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

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。