{{ item.name }}
{{ item.name }}

{{ it.name }}

{{ it.text }}

{{ it.name }}

{{ innerIt.name }}

{{ innerIt.text }}

{{news.time}}
{{news.title}}
MySQL 字符集再探
2022-03-29发布 2,605浏览

1、字符集

  • ASCII 是最基础的字符集,每个 ASCII 字符占用1字节,ASCII 仅利用了8位编码能力的一半,最高位恒为 0 。

  • Latin1 字符集利用剩下的一半编码了西欧常用字母。

  • UCS-2 使用2字节编码,容量为65536 。

  • UTF-16 在这基础上, 增加了临时使用2个2字节,编码特殊字符的能力。

  • UTF-32 使用定长4字节编码。

  • GB系列、UTF-8 等字符集,0~127编码和 ASCII 一样,使用单字节。在最高位不为0时,额外使用1~3字节编码。

  • 即它们是变长编码,每个字符占用1~4字节

只表达 ASCII 0~127字符的话,Latin1、GB系列、UTF8 等编码是完全相同的. 而 UTF16 和 UTF32 则会有额外的空白。

image

使用如下 SQL 语句可以看到当前 MySQL 实例支持的字符集(和 collation )。

image

题外:什么是 collation


image

MySQL文档

MySQL文档( https: v.mysql.com/doc/refman/8.0/en/adding-collation.html):collation 是进行字符串比较或排序时使用的规则。例如:

大小写是否敏感(case sensitive / insensitive)特殊的相等规则: ij = ij

2、MySQL 系列参数

执行 SQL show variables like 'character%' 可以获得 MySQL 中关于字符集的几个参数。

image

2.1 参数 character_set_clientcharacter_set_client 并不是客户端使用的字符集。

用户输入什么数据,客户端就发送什么数据。字符集由用户输入决定。

character_set_client 是服务端的参数。

服务端认为客户端发来的数据是以 character_set_client 编码的。

character_set_client不能被设置为以下几个字符集 (参考链接:https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-impermissible-client-charset)

3、一个乱码原因的勘误

mysql> select * from ytt_new10.t2;
a1   

事实上,MySQL 知道character_set_client = gb2312,也知道t1表编码为 utf8 。写入过程中,MySQL 会进行转换,不应当发生乱码。

发生乱码的真正原因是:我们发送给 MySQL 的数据 ,并不是以 gb2312 编码的。是我们欺骗了 MySQL 。

insert ... "("病毒滚吧!")这个语句, 是以终端字符集 utf8 编码的. MySQL 把 utf8 数据当作 gb2312 数据, 转换成 utf8 数据, 自然产生了乱码。

让我们以 gb2312 发送数据:

# 终端编码为UTF-8. 使用iconv转换文件编码.
$ echo 'insert into ytt_new10.t1 val("病毒滚吧!");' | iconv -f utf8 -t gb2312 > insert-gb.txt
$ cat insert-gb.txt # 终端无法正常显示GB2312字符
insert into t1 val("???????ɣ?");
$ mysql -h ... --default-character-set=gb2312 < insert-gbk.txt

SELECT 时,MySQL 会把数据转换成character_set_results再返回给客户端。终端可能不支持非 UTF8 字符的显示,需要转换。

$ mysql ... --default-character-set=utf8 -e 'select * from ytt_new10.t1'
病毒滚吧!
$ mysql ... --default-character-set=gb2312 -e 'select...' | iconv -f gb2312 -t utf8
病毒滚吧!

4、字符集 client 到 connection 转换的意义

收到客户端发来的语句后, 服务端会将语句从 character_set_client 转换为 character_set_connection

这个步骤乍一看多此一举

直接以client字符集执行,MySQL 也会正常转换到表字符集。也可以让客户端直接以connection字符集发送语句。那么,为什么不将两个参数合并呢?搜索发现,使用转换层的潜在原因如下:不同字符集的某些行为是完全不同的:mysql> set character_set_connection = 'utf8';
mysql> select length("hello");
|               5 |
mysql> set character_set_connection = 'utf32';
mysql> select length("hello");
|              20 |

由于character_set_client的限制,客户端不能直接以 UTF32 等字符集发送语句。如果我们就是想要 UTF32 下的行为(函数结果、排序规则等),就需要由 MySQL 进行一层转换。


上一篇
MySQL 用户密码过期那点事
400-820-6580 13916131869
marketing@actionsky.com
上海市闵行区万源路2138号泓茂中心2号楼
产品详情
关系型数据库
AI数据库
数据库智能管理平台
数据库生态产品
行业案例
金融行业
新零售行业
制造业
通信行业
更多
公司动态
最新新闻
国产化信息
技术分享
关于我们
公司简介
公司分布
国家专利
资质认证
扫码关注公众号
© Copyright 2017, All rights reserved by: 上海爱可生信息技术股份有限公司 沪ICP备12003970号-1 | 法律声明 | 网站地图
沪公网安备 31010402003331号