MySQL 字符集 utf8 与 utf8mb4

前言

为什么需要字符集?

首先,我们知道计算机存储的都是 0 1 这样的二级制序列,各种字符如 字母、汉字、符号等如何写进计算机?

答案就是 映射,我们先定义字符集,比如 UTF-8,其收录全世界很多字符,然后给每个字符定义一串唯一的、由 0 1 组成的二进制序列,这就是每一个字符在计算机中的身份。

编码过程:通过字符集映射规则,将字符转化成 0 1 二进制序列的过程

解码过程:将 0 1 的计算机二进制序列转化为 字符集的过程

因此,编码、解码需要使用同一个字符集规则,否则就是乱码

MySQL utf8 与 utfmb4

字符集

UTF-8:几乎收录了全世界各个国家和地区使用的字符,而且还在不断扩充,这种字符集兼容 ASCII 字符集,采用 变长编码方式,编码一个字符时需要使用 1-4 字节。

UTF-16:使用 2 或者4字节编码一个字符

UTF-32:使用4字节编码一个字符。

Unicode 字符集:本质来说和 UTF 是一套编码方案。Unicode 字符集可以采用 UTF-8、UTF-16、UTF-32 几种编码方案

utf8 和 utfmb4

前面讲到,UTF-8字符集需要 1-4 字节,但是我们常用的字符使用 1-3 字节表示就够了。

在 MySQL 中,字符集表示一个字符所用的最大字节长度,在某些方面会影响系统的存储和性能。因此,MySQL 在设计时,定义了两种概念:

  1. utf8mb3:"阉割" 过的 UTF-8 字符集,只使用 1-3 字节表示字符
  2. utf8mb4:正宗的 UTF-8 字符集,使用 1-4 字节表示字符

值得注意的是,在 MySQL 中,utf8 是 utf8mb3 的别名,所以如果使用 utf8 字符集意味着只使用 1-3个字节存储。如果用到 emoji 表情 则可能需要使用 utf8mb4。

在 MySQL 8.0 中,已经将 utf8mb4 设置为默认的字符集。

MySQL 字符集使用规则

在MySQL中,字符集和排序规则的设置可以在多个层级上进行,包括服务器级、数据库级、表级和列级。下面我将详细展开如何在这些不同层级上设置字符集。

1. 服务器级字符集设置

在MySQL服务器启动时,可以通过配置文件(如my.cnf或my.ini)设置默认的字符集和排序规则:

ini 复制代码
[mysqld] 
character-set-server=utf8mb4 
collation-server=utf8mb4_unicode_ci

2. 数据库级字符集设置

创建数据库时,可以指定字符集和排序规则:

sql 复制代码
CREATE DATABASE your_database_name
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

如果数据库已经存在,可以使用以下命令更改字符集:

sql 复制代码
ALTER DATABASE your_database_name
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

3. 表级字符集设置

创建表时,可以为整个表指定字符集和排序规则:

sql 复制代码
CREATE TABLE your_table_name (
    id INT PRIMARY KEY,
    name VARCHAR(255)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

如果表已经存在,可以使用以下命令更改字符集:

sql 复制代码
ALTER TABLE your_table_name
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

4. 列级字符集设置

在创建或修改表时,可以为特定的列指定字符集和排序规则:

sql 复制代码
CREATE TABLE your_table_name (
    id INT PRIMARY KEY,
    name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
);

如果需要修改现有列的字符集,可以使用以下命令:

sql 复制代码
ALTER TABLE your_table_name
MODIFY COLUMN name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

值得注意的是:如果列中部分字符无法通过修改后的字符集展示,则会发生错误。比如,最开始列字段使用 utf8 字符集,并且存储了一些汉字,此时换成 ASCII 字符集则会出错。

5. 连接级字符集设置

在连接到MySQL时,可以通过设置连接字符集来确保数据的正确传输。通常在连接字符串中指定:

sql 复制代码
SET NAMES 'utf8mb4';

在Java中,使用JDBC连接时,可以在连接URL中指定字符集:

ini 复制代码
String url = "jdbc:mysql://localhost:3306/your_database_name?useUnicode=true&characterEncoding=utf8mb4";

值得注意的是:设置字符集和排序规则时,确保在所有层级上保持一致,以避免字符编码问题。特别是在多语言环境中,使用utf8mb4字符集可以确保支持所有Unicode字符,包括表情符号。

6. MySQL server 与 client 交互过程字符集转换

字符集和排序规则的设置是确保数据正确存储、检索和显示的关键。以下是对各个字符集相关系统变量的详细解释及其用途:

1. character_set_server

  • 用途:这是MySQL服务器的默认字符集。当创建新的数据库或表时,如果没有显式指定字符集,将使用这个默认字符集。
  • 影响:影响所有新创建的数据库和表的默认字符集,除非在创建时另有指定。

2. collation_server

  • 用途:这是服务器的默认排序规则,与character_set_server一起使用。排序规则决定了字符串比较和排序的方式。
  • 影响:影响新创建的数据库和表的默认排序规则,除非在创建时另有指定。

3. character_set_database

  • 用途:表示当前选定数据库的字符集。当你选择一个数据库后,这个变量会自动更新为该数据库的字符集。
  • 影响:影响在该数据库中创建的新表的默认字符集。

4. character_set_client

  • 用途:表示客户端发送给服务器的SQL语句的字符集。客户端在发送数据到服务器时,数据会被转换为这个字符集。
  • 影响:确保客户端发送的数据在服务器端能够被正确解析。

5. character_set_connection

  • 用途:表示服务器在解析客户端发送的SQL语句时使用的字符集。通常与character_set_client相同。
  • 影响:影响SQL语句的解析和执行。如果字符集不匹配,可能导致SQL语句中的字符串无法正确解析。

6. character_set_results

  • 用途:表示服务器发送给客户端的查询结果的字符集。服务器在将数据返回给客户端时,会将数据转换为这个字符集。
  • 影响:确保客户端能够正确显示从服务器接收到的数据。

具体应用场景

  • 数据插入和查询:当客户端插入数据时,数据会根据character_set_client进行编码,然后在服务器端根据character_set_connection进行解析和存储。查询结果则根据character_set_results进行编码后发送给客户端。
  • 字符集转换:如果客户端和服务器之间的字符集设置不一致,MySQL会在不同字符集之间进行转换。这可能导致性能下降或数据丢失,因此建议在客户端和服务器之间使用一致的字符集设置。

MySQL 各级别规则使用

  • 如果创建和修改列时,没有指定字符集和比较规则,则该列默认使用表的字符集和比较规则
  • 如果创建表时没有显示指定字符集和比较规则,则该表默认使用数据库的字符集和比较规则
  • 如果创建数据库时没有显示指定字符集和比较规则,则该数据库默认使用服务器的字符集和比较规则
相关推荐
阿里小阿希几秒前
Vue3 + Element Plus 项目中日期时间处理的最佳实践与数据库设计规范
数据库·设计规范
且行志悠1 小时前
Mysql的使用
mysql
xuxie131 小时前
SpringBoot文件下载(多文件以zip形式,单文件格式不变)
java·spring boot·后端
白鹭1 小时前
MySQL源码部署(rhel7)
数据库·mysql
重生成为编程大王1 小时前
Java中的多态有什么用?
java·后端
666和7771 小时前
Struts2 工作总结
java·数据库
还听珊瑚海吗1 小时前
SpringMVC(一)
数据库
Funcy2 小时前
XxlJob 源码分析03:执行器启动流程
后端