mysql gbk编码不全_一次MySQL GBK编码的故障分析

用户在MySQL for .NET Connector使用GBK字符集时,遇到中文字符串含全角字符导致的语法错误。分析发现,驱动在处理时对全角和半角单引号进行转义,外层单引号导致冲突。在GBK编码下,某些汉字组合可能导致转义失败,而UTF8编码能避免这类问题。
摘要由CSDN通过智能技术生成

最近有用户遇到MySQL GBK字符集的一个坑,我也是第一次遇到,网上也没看此类case,所以整理了故障分析报告分享给大家,供参考。

故障描述

用户描述说:在使用MySQL for .NET Connector的时候,MySQL客户端和服务端的字符集设置都是GBK的情况下,遇到中文输入中夹杂全角字符提示语法错误,不清楚为何被添加了转义符号,怀疑和全角字符有关。

从错误提示来看,有这几个表现:

字符串中间的全角单引号字符被加上了反斜杠转义;

字符串末尾的半角单引号字符被加上了反斜杠转义;

整个字符串被单引号包裹;

提示语法错误,而非数据格式相关错误。

故障分析

首先需要查看下 .net 驱动源码,确认以上1、2、3现象确实是驱动行为。

这里定义了需要转移哪些字符,其中包括全角和半角单引号了。

enum CharClass : byte

{

None,

Quote,

Backslash

}

private static string stringOfBackslashChars = "\u005c\u00a5\u0160\u20a9\u2216\ufe68\uff3c";

private static string stringOfQuoteChars =

"\u0022\u0027\u0060\u00b4\u02b9\u02ba\u02bb\u02bc\u02c8\u02ca\u02cb\u02d9\u0300\u0301\u2018\u2019\u201a\u2032\u2035\u275b\u275c\uff07";

private static CharClass[ ] charClassArray = makeCharClassArray();

为这些字符添加反斜杠转义符

数据写入时最外层会用单引号包裹。

通过这些代码可以验证了上述几个现象。全角半角单引号字符确实会被转义;

转义原因是外层使用的单引号。

通过这些现象,我猜测是因为转义失败导致。接下来通过一些方法重现故障场景,验证我的猜想。

首先验证在utf8编码下的表现,无论外层是双引号还是单引号,内部的单引号都能正常转义。

然后验证在gbk编码下的表现,字符串包含汉字的情况下,提示语法错误与用户遇到的错误一致,重现故障场景。

mysql> select hex('茅\'');

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''茅\'')' at line 1

mysql> select hex("茅\'");

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

| hex("茅\'") |

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

| E88C855C27 |

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

1 row in set (0.00 sec)

无汉字夹杂可以正常转义。

验证是否和全角字符有关,也可以正常转义,说明不是全角字符影响。

总结

通过以上的分析,证实了我的猜想,因为转义失败导致字符串内的单引号与外部单引号冲突,从而看到提示语法错误。

在GBK编码下如果中文字符串中带引单引号可能会导致转义失败。为什么是可能呢,因为我后续又尝试了一些其他汉字也有可以正常转义的,原因不详,如果有对字符编码特别熟悉的朋友知道原因请告诉我。

最终由于用户无法调整字符集编码,也无法对输入字符串做过滤,只能将驱动的单引号改成双引号来解决此问题。

我的建议还是使用utf8编码更好,只是比gbk多1个字节的空间占用,开销并不大,而且从MySQL 5.5.3也支持了utf8mb4,未来MySQL 8.0默认也是utf8mb4,到那个时候就不会有各种乱码的困扰了。网上随便一搜,可以发现编码问题还是让不少使用MySQL用户头疼的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值