mysql y_关于MySQL中Y和~问题

最近在坛子里还看到说到Y和~的问题,不知道mysql官方的bugs里面安排到什么时候解决这个bug。这里描述一下,说明一下原因。

1、问题描述

mysql> create table t (c char(32)) engine=innodb;

Query OK, 0 rows affected (0.01 sec)

mysql> insert into t values('Y');

Query OK, 1 row affected (0.02 sec)

mysql> insert into t values('~');

Query OK, 1 row affected (0.00 sec)

mysql> select * from t where c='Y';

+------+

| c|

+------+

| Y|

| ~|

+------+

2 rows in set (0.00 sec)

上面的语句和显示结果容易看出,where c=’Y’的条件匹配到了‘~’.

2、源码修改

打开strings/ctype-gbk.c,查看sort_order_gbk这个结构体,这里是gbk的码表。可以看到第157行为”'X','Y','Z','{','|','}','Y','\177',”.这里第二个’Y’明显错误,将其改为’~’,重新编译,执行新的mysqld,

上述最后一个语句结果为

mysql> select *from t where c='Y';

+------+

| c|

+------+

| Y|

+------+

1 row in set (0.00 sec)

3、原因说明

我们来分析一下strings/ctype-gbk.c的这个函数my_strnncoll_gbk_internal。当使用gbk字符时,在作字符串匹配的时候,调用此函数。

int my_strnncoll_gbk_internal(const uchar **a_res, const uchar **b_res,

size_t length)

{

const uchar *a= *a_res, *b= *b_res;

uint a_char,b_char;

while (length--)

{

if ((length > 0) && isgbkcode(*a,*(a+1)) && isgbkcode(*b, *(b+1)))

{

a_char= gbkcode(*a,*(a+1));

b_char= gbkcode(*b,*(b+1));

if (a_char != b_char)

return ((int) gbksortorder((uint16) a_char) -

(int) gbksortorder((uint16) b_char));

a+= 2;

b+= 2;

length--;

}

else if (sort_order_gbk[*a++] != sort_order_gbk[*b++])

return ((int) sort_order_gbk[a[-1]] -

(int) sort_order_gbk[b[-1]]);

}

*a_res= a;

*b_res= b;

return 0;

}

第8行是作中文判断的,先忽略。在我们的例子中,走的是第19行的判断。

可以看到,在判断字符值是否相同时使用sort_order_gbk[*a++] != sort_order_gbk[*b++]。当我们的*a=’~’, *b=’Y’时,由于上面说到的157行的原因,被判定为值相同。

(作为辅助验证,如果有兴趣把第二个’Y’改成‘Z’,以后Z和~就相同了)。

4、其他解决方法

如果不改源码,也有”解决方法”

1)使用binary查询

使用binary查询后,整个字符串对照流程都与gbk无关,因此不会碰到这个bug。副作用是导致大小写敏感。

2)换字符集

从strings/目录下的各个ctype-*.c看,只有gbk和gb2312有这个问题,因此改成utf-8,自然没有这个问题。副作用是改变了原有数据长度,且涉及到重做表。

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2010-11-09 11:29

浏览 2527

论坛回复 / 浏览 (1 / 1706)

分类:数据库

评论

2 楼

nofreezou

2012-09-21

LZ要先说一下mysql什么版本,我在mysql5.1.54上测试是没有这个问题的

另外再请教一个问题,strings/ctype-gbk.c 里面gbk转unicode的编码不全,这个bug为啥没人提呢?  如 static uint16 tab_gbk_uni0[]的最后,很多都是0,但是真正的gbk编码后面的还是有值的 如过set names gbk,添加到一个utf8的表里面,这样的字符就丢失了

另外有空希望LZ再写些文章介绍下源代码相关的事~~比如里面很多奇怪的变量名、文件名

966903dea4bcb507358d5dcce8b912e5.gif

1 楼

babaoqi

2010-11-25

顶一个,学习一下!

没研究过这么深呢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值