在使用数据库服务时,有时在数据库表中输入中文信息条目时,默认经常会遇到字符乱码问题,输入中文信息为什么会出现乱码:

ASCII码

00000000 = 0-255 00000001 a 00000010 b

美国发布的,⽤1个字节(8位⼆进制)来表示⼀个字符,共可以表示2^8=256个字符。

美国的国家语⾔是英语,只要能表示0-9、 a-z、 A-Z、特殊符号。

ANSI编码:

每个国家为了显示本国的语⾔,都对ASCII码进⾏了扩展。

⽤2个字节(16位⼆进制)来表示⼀个汉字,共可以表示2^16= 65536个汉字。

中国的ANSI编码是GB2312编码(简体),对6763汉字进⾏编码,含600多特殊字符。另外还有GBK(简体)。

⽇本的ANSI编码是JIS编码。

台湾的ANSI编码是BIG5编码(繁体)

GB2312编码

gb2312 是国标,是中国的字库,⾥⾯仅涵盖了汉字和⼀些常用外文,比如常见的符号。

GBK编码

对GB2312进⾏了扩展,⽤来显示罕⻅的、古汉语的汉字。现在已经收录了2.1万左右。并提供了1890个汉字码 位。 K的含义就是“扩展”。

Unicode编码(统⼀编码)

⽤4个字节(32位⼆进制)来表示⼀个字符,想法不错,但效率太低。

UTF-8(Unicode Transform Format)编码

UTF-8是国际通⽤字库,⾥⾯涵盖了所有地球上所有⼈类的语⾔⽂字,⽐如阿拉伯⽂、汉 语、⻦语……

根据字符的不同,选择其编码的⻓度。⽐如:⼀个字符A⽤1个字节表示,⼀个汉字⽤2个字节表示。

字库规模: UTF-8(字很全) > gb2312(只有汉字)

utf8和utf8mb4之间有什么区别?

utf8:最多存储3字节长度字符,如汉字

utf8mb4:最多存储4字节长度字符,如表情、汉字

PS: 企业生产环境中,建议客户端与服务端字符集要统一;

字符编码

查看数据库服务支持的字符编码

mysql> show charset;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| binary   | Binary pseudo charset           | binary              |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| utf8mb3  | UTF-8 Unicode                   | utf8mb3_general_ci  |      3 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_0900_ai_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)

查看当前数据库服务的字符编码

mysql> show variables like "%character%";
+--------------------------+---------------------------------------------------------+
| Variable_name            | Value                                                   |
+--------------------------+---------------------------------------------------------+
| character_set_client     | utf8mb4       # 客户端向服务器发送数据时所使用的字符集。       |
| character_set_connection | utf8mb4                                                 |
| character_set_database   | utf8mb34                                                |
| character_set_filesystem | binary                                                  |
| character_set_results    | utf8mb4       # 服务器向客户端返回结果时所使用的字符集。       |
| character_set_server     | utf8mb4       # MySQL服务器的默认字符集。 新建库、表         |
| character_set_system     | utf8mb3       # 元数据存储的字符集。                       |
| character_sets_dir       | /usr/local/mysql-8.0.37-linux-glibc2.17-x86_64/share/charsets/                     # 查找字符集定义的文件系统的目录位置。          |
+--------------------------+---------------------------------------------------------+
8 rows in set (0.03 sec)

说明:数据库服务最新8.0版本的字符集信息为utf8mb4,早期数据库服务版本字符集编码为latin1;

参数信息解释说明
character_set_client客户端使用的字符集
`character_set_connection连接数据库时的字符集 如果程序中没有指明连接数据库使用的字符集类型则按照这个字符集设置。
character_set_database默认创建数据库的编码格式 如果在创建数据库时没有设置编码格式,就按照这个格式设置。
character_set_filesystem文件系统的编码格式,把操作系统上的文件名转化成此字符集 即把 character_set_client转换character_set_filesystem, 默认binary是不做任何转换
character_set_results数据库给客户端返回时使用的编码格式,如果没有指明,使用服务器默认的编码格式。
character_set_server服务器安装时指定的默认编码格式,这个变量建议由系统自己管理,不要人为定义。
character_set_system数据库系统使用的编码格式,这个值一直是utf8 不需要设置,它是为存储系统元数据的编码格式。
character_sets_dir字符集安装的目录

流程:

根据客户端请求数据库服务端字符集转换流程,可以更好的理解以上字符编码配置参数:

  1. mysql Server收到请求时将请求数据从 character_set_client 转换为 character_set_connection;

  2. 进行内部操作前将请求数据从 character_set_connection 转换为内部操作字符集;

    • 使用每个数据字段的 CHARACTER SET 设定值;

    • 若上述值不存在,则使用对应数据表的字符集设定值;

    • 若上述值不存在,则使用对应数据库的字符集设定值;

    • 若上述值不存在,则使用 character_set_server 设定值;

  3. 最后将操作结果从内部操作字符集转换为 character_set_results

修改数据库客户端字符编码

vim /etc/my.cnf.d/client.cnf
[client]
default-character-set=utf8mb4

修改完重启数据库服务

建数据库时单独设置字符集

image-20240620001925684

新建表时单独设置字符编码

image-20240620002205731

修改数据库表字符编码

假设数据库表原有字符集为gbk,并且已经存储数据了,需要将表和数据字符集进行调整转换utf8mb4

方法一: 只会影响之后存储的数据,不会修改之前存储的数据

mysql > alter table t1 charset utf8mb4; 

方法二:

  1. 锁表逻辑导出数据(例如: mysqldump)
  2. 重新创建数据空表(设置目标字符集)
  3. 导入备份数据信息

严谨的方法,可以影响之后存储的数据,也会修改之前存储的数据

字符集转换是可以的,但是必须保证修改后的字符集是修改前的严格超集(包含)

校对规则(排序规则)

指字符比较时按照字符编码还是直接用二进制数据比较,以及是否区分大小写。

根据校对规则定义或设置的不同:在查询数据信息时,影响数据信息的查询输出和排序效果;

其中utf8mb4字符集中,常用的排序规则有utf8mb4_unicode_ciutf8mb4_general_ciutf8mb4_bin

排序规则前缀是字符集编码,中间是排序规则名称,后缀有特殊意义如下(常用的):

排序规则后缀解释说明
_ci不区分大小写,Case-insensitive的缩写
_cs区分大小写,Case-sensitive的缩写
_ai不区分重音,Accent-insensitive的缩写
_as区分重音,Accent-sensitive的缩写
_bin采用二进制方式存储数据信息v

查看数据库服务中可用的校对信息

image-20240620004737062

设置数据库字符编码校对规则

image-20240620005957935

设置表字符编码校对规则

image-20240620010158725