前言
为什么需要字符集?
首先,我们知道计算机存储的都是 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 在设计时,定义了两种概念:
- utf8mb3:"阉割" 过的 UTF-8 字符集,只使用 1-3 字节表示字符
- 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 各级别规则使用
- 如果创建和修改列时,没有指定字符集和比较规则,则该列默认使用表的字符集和比较规则
- 如果创建表时没有显示指定字符集和比较规则,则该表默认使用数据库的字符集和比较规则
- 如果创建数据库时没有显示指定字符集和比较规则,则该数据库默认使用服务器的字符集和比较规则