目录
-
- 核心区别
- 详细对比
-
- [1. **编码范围不同**](#1. 编码范围不同)
- [2. **历史背景**](#2. 历史背景)
- [3. **实际影响最明显的场景**](#3. 实际影响最明显的场景)
- [4. **存储空间差异**](#4. 存储空间差异)
- [5. **性能差异**](#5. 性能差异)
- 关键限制
- 实际使用建议
-
- [1. **新项目一律使用utf8mb4**](#1. 新项目一律使用utf8mb4)
- [2. **现有系统迁移步骤**](#2. 现有系统迁移步骤)
- [3. **连接配置**](#3. 连接配置)
- [4. **排序规则选择**](#4. 排序规则选择)
- 兼容性考虑
- 验证当前设置
- 总结建议
核心区别
utf8在MySQL中是一个"不完整"的UTF-8实现 ,而utf8mb4才是真正的UTF-8实现。
详细对比
1. 编码范围不同
| 字符集 | 最大字节数 | 支持的Unicode范围 | 备注 |
|---|---|---|---|
| utf8 | 3字节 | BMP平面(U+0000 ~ U+FFFF) | 不支持4字节字符 |
| utf8mb4 | 4字节 | 所有Unicode字符(包括Supplementary Planes) | 完整UTF-8支持 |
2. 历史背景
- utf8 (utf8mb3) : MySQL早期实现的"阉割版"UTF-8
- 2003年引入,当时认为3字节足够表示所有字符
- 实际是UTF-8的一个子集,后来更名为
utf8mb3
- utf8mb4 : MySQL 5.5.3引入
- 完整的UTF-8实现
- "mb4" = "multi-byte 4"
3. 实际影响最明显的场景
sql
-- 这些字符在utf8下会出错,在utf8mb4下正常
-- 表情符号(Emoji)
INSERT INTO users (name) VALUES ('小明😊开心'); -- 需要utf8mb4
-- 部分生僻汉字
INSERT INTO text (content) VALUES ('𠀀𪚥𪚨'); -- 需要utf8mb4
-- 某些数学符号、音乐符号等
INSERT INTO symbols (symbol) VALUES ('𝄞𝄢'); -- 需要utf8mb4
4. 存储空间差异
sql
-- 创建表对比
CREATE TABLE test_utf8 (
id INT,
text VARCHAR(100) CHARACTER SET utf8 -- 最大300字节
);
CREATE TABLE test_utf8mb4 (
id INT,
text VARCHAR(100) CHARACTER SET utf8mb4 -- 最大400字节
);
-- 注意:VARCHAR(100)对于utf8最多存储100个字符(但可能占用最多300字节)
-- 对于utf8mb4最多存储100个字符(但可能占用最多400字节)
5. 性能差异
| 方面 | utf8 | utf8mb4 | 说明 |
|---|---|---|---|
| 存储空间 | 较小 | 较大 | utf8mb4可能多用约33%空间 |
| 索引长度 | 较短 | 较长 | 索引长度限制以字节为单位 |
| 排序性能 | 稍快 | 稍慢 | 差异通常不明显 |
关键限制
索引长度限制
sql
-- utf8: 最大索引长度 767字节
-- utf8mb4: 最大索引长度 3072字节(MySQL 5.7+)
-- 但在早期版本中,InnoDB对utf8mb4的索引限制:
-- utf8: VARCHAR(255) 可以建索引 (255×3=765 < 767)
-- utf8mb4: VARCHAR(255) 不能建索引 (255×4=1020 > 767)
-- 需要改为 VARCHAR(191) (191×4=764 < 767)
-- 解决办法:修改innodb_large_prefix设置
SET GLOBAL innodb_large_prefix = ON;
SET GLOBAL innodb_file_format = Barracuda;
实际使用建议
1. 新项目一律使用utf8mb4
sql
-- 数据库级别
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 表级别
CREATE TABLE mytable (
id INT PRIMARY KEY,
content TEXT
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 列级别
ALTER TABLE mytable MODIFY content VARCHAR(255)
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2. 现有系统迁移步骤
sql
-- 1. 备份数据
-- 2. 修改数据库默认字符集
ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 3. 修改表字符集
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 4. 修改连接配置
-- 在my.cnf中:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
-- 5. 验证修改
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
3. 连接配置
bash
# 命令行连接
mysql -u root -p --default-character-set=utf8mb4
# 应用程序连接示例
# Python (PyMySQL)
conn = pymysql.connect(charset='utf8mb4')
# PHP (PDO)
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', $user, $pass);
# Java (JDBC)
jdbc:mysql://localhost:3306/db?characterEncoding=utf8mb4
4. 排序规则选择
sql
-- 常用排序规则
utf8mb4_unicode_ci -- 基于Unicode标准排序,支持多语言(推荐)
utf8mb4_general_ci -- 旧的排序规则,性能稍好但准确性较差
utf8mb4_bin -- 二进制排序,区分大小写和重音
utf8mb4_0900_ai_ci -- MySQL 8.0默认,基于Unicode 9.0标准
-- 查看所有utf8mb4排序规则
SHOW COLLATION LIKE 'utf8mb4%';
兼容性考虑
向下兼容性
- utf8mb4完全兼容utf8(utf8mb3)存储的数据
- 反向不兼容:utf8mb4的数据可能无法在utf8中正常显示
客户端兼容性
- 所有现代客户端都支持utf8mb4
- 确保客户端连接时也使用utf8mb4字符集
验证当前设置
sql
-- 查看数据库、表、列的字符集
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND CHARACTER_SET_NAME IS NOT NULL;
-- 查看当前连接的字符集
SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';
总结建议
- 始终使用utf8mb4,不要使用utf8
- 排序规则使用utf8mb4_unicode_ci(或MySQL 8.0的utf8mb4_0900_ai_ci)
- 注意索引长度限制,必要时调整字段长度
- 确保应用程序连接字符串也使用utf8mb4
- MySQL 8.0已将utf8mb4作为默认字符集
sql
-- MySQL 8.0默认设置
mysql> SELECT @@character_set_database, @@collation_database;
+--------------------------+------------------------+
| @@character_set_database | @@collation_database |
+--------------------------+------------------------+
| utf8mb4 | utf8mb4_0900_ai_ci |
+--------------------------+------------------------+
重要提示 :MySQL未来版本中,utf8可能会被重新定义为真正的UTF-8(目前utf8是utf8mb3的别名),建议明确使用utf8mb4以避免不确定性。