最近在坛子里还看到说到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,自然没有这个问题。副作用是改变了原有数据长度,且涉及到重做表。
分享到:
相关推荐
MySQL集群(一台主机安装MariaDB与MySQL同时运行) 以下是在已安装MySQL的情况下,安装MariaDB的主要步骤. [root@mariadb-near-mysql ~]# cat /etc/issue CentOS release 6.2 (Final) [root@mariadb-near-...
C++使用mysql++y调用mysql的例子
这是MySQL参考手册的翻译版本,关于MySQL参考手册,请访问:dev.mysql.com。 原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的。
yum -y remove mysql-libs-5.1.52-1.el6_0.1.i686 卸载二: 输入: #rpm -qa | grep -i mysql 显示: MySQL-client-5.1.62-1.glibc23.i386 MySQL-server-5.1.62-1.glibc23.i386 卸载方法: #rpm -ev MySQL-client-...
最近在维护服务器的时候,突然发现MySQL无法使用了,于是在“控制面板”-添加/删除程序“中删除了MySQL,重启了一下服务器再安装MySQL。 本来以为可以一路很顺利地Next下去的,但是事与愿违。运行“MySQL Server ...
MySql完整教程笔记
非MySQL安装MySQL-python,有时不是数据库为封装的MySQL时,可以通过yum -y install mysql-devel 但有时不行,这是可按文档去更改MySQL-python
yum -y remove mysql-libs-5.1.52-1.el6_0.1.i686 卸载二: 输入: #rpm -qa | grep -i mysql 显示: MySQL-client-5.1.62-1. glibc23.i386 MySQL-server-5.1.62-1.glibc23.i386 卸载方法: #rpm -ev MySQL-client-...
在 MySQL 3.23 中,如果表达式的右边是一个日期值或一个日期时间型字段,你可以使用 + 和 - 代替 DATE_ADD() 和 DATE_SUB()(示例如下)。 参数 date 是一个 DATETIME 或 DATE 值,指定一个日期的...
#适用于实时查询mysql占用CPU高的语句,循环监控mysql进程情况,当CPU大于一定的前执行中的SQL情况. #执行前,修改ENV认证部分 #编写:Chaoren #2022年3月4日18:38:53 # #对于执行时间非常短的SQL可能监控到的语句...
在centos如何安装MySQL 1.Rpm -qa | grep mysql -------查看是否安装了mysql 2.Yum -y install mysql----卸载无关组件 新手博主上传,请见谅
利用crontab,系统每天定时备份mysql数据库 利用系统crontab来定时执行备份文件,按日期对备份结果进行保存,达到备份的目的。 1、创建保存备份文件的路径/mysqldata #mkdir /mysqldata 2、创建/usr/sbin/...
在mysql中使用SELECT STR_TO_DATE()函数将字符串日期转为日期型: SELECT STR_TO_DATE('2012~8~8 14.58.09','%Y~%m~%d %k.%i.%s' ); STR_TO_DATE('2012-8-8 14:58:09','%Y-%m-%d %k:%i:%s' ) A;;STR_TO_DATE('...
/bin/sh#使用前安装yum -y install perl-DBD-MySQL perl-Digest-MD5 perl-DBI libev#yum install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL -y#yum -y install rsync perl l perl-Digest...
Oracle和mysql的一些简单命令对比 1) SQL> select to_char(sysdate,’yyyy-mm-dd’) from dual; SQL> select to_char(sysdate,’hh24-mi-ss’) from dual; mysql> select date_format(now(),’%Y-%m-%d’); mysql> ...
安装MySQL。 [root@sample ~]# yum -y install mysql-server ← 安装MySQL [root@sample ~]# yum -y install php-mysql ← 安装php-mysql
MySQL中文拼音数据库(6565字,全拼+首字母(大小写均有)) 里面的文件内容大体是这个样子的。(压缩包中包含sql文件,可以直接导入) INSERT INTO `hs_pinyin` VALUES (3, '在', 'zai', 'z', 'Z'); INSERT INTO `...
MySQL 企业版审计功能使用“mysql”系统数据库存储过滤条件和用户的账户数据,为了增加灵活性,此版本增添了一个“audit_log_database”服务器系统变量,在服务器启动时可以指定到其他的数据库。 MySQL 企业版数据...
一、安装MySQL 1、安装cmake cd /usr/local/src tar zxvf cmake-2.8.11.2.tar.gz cd cmake-2.8.11.2 ./configure make make install 2、安装MySQL groupadd mysql #添加mysql组 useradd -g mysql mysql -s...
您可能感兴趣的文章:MySQL中日期比较时遇到的编码问题解决办法PHP以及MYSQL日期比较方法mysql 获取当前日期函数及时间格式化参数详解mysql unix准换时间格式查找指定日期数据代码MySql日期查询语句详解深入mysql ...