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 各级别规则使用

  • 如果创建和修改列时,没有指定字符集和比较规则,则该列默认使用表的字符集和比较规则
  • 如果创建表时没有显示指定字符集和比较规则,则该表默认使用数据库的字符集和比较规则
  • 如果创建数据库时没有显示指定字符集和比较规则,则该数据库默认使用服务器的字符集和比较规则
相关推荐
阑梦清川33 分钟前
linux基础--文件描述符&&输出重定向的理解
后端
程序员三明治1 小时前
【重学数据结构】队列 Queue
数据结构·后端·算法
杜小暑1 小时前
数据结构之双向链表
c语言·数据结构·后端·算法·链表·动态内存管理
豆浆Whisky1 小时前
Go实现百万级连接:资源管控与性能平衡的艺术|Go语言进阶(9)
后端·go
majunssz1 小时前
深入剖析Spring Boot依赖注入顺序:从原理到实战
java·数据库·spring boot
南棱笑笑生2 小时前
20250931在RK3399的Buildroot【linux-6.1】下关闭camera_engine_rkisp
开发语言·后端·scala·rockchip
比特森林探险记2 小时前
MySQL 架构全景解析
数据库·mysql·架构
数字冰雹2 小时前
图观 流渲染场景服务器
服务器·前端·数据库·数据可视化
MetetorShower2 小时前
深入解析MCP:从Function Calling到工具调用的标准化革命
后端