0%

存储表情符号

MySQL 存储表情符号:utf8 与 utf8mb4 的区别及解决方案

MySQL 中存储表情符号(如 😄、🎉 等)时出现的 Incorrect string value 错误,根源是字符集对 Unicode 编码的支持不全。默认的 utf8 字符集无法存储 4 字节的表情符号,需改用 utf8mb4 字符集。本文详细解析两者的区别及完整解决方案。

错误原因:utf8 字符集的局限性

MySQL 中的 utf8 字符集存在设计缺陷:

  • 实际是 utf8mb3 的别名,仅支持最多 3 字节 的 Unicode 字符。
  • 而表情符号(如 😄 的 Unicode 编码为 U+1F604)属于 4 字节字符,超出了 utf8mb3 的存储范围,因此插入时会报错:
    1366 - Incorrect string value: '\xF0\x9F\x98\x84' for column 'name' at row 1

utf8 与 utf8mb4 的核心区别

字符集 最大字节数 支持的 Unicode 范围 能否存储表情符号 适用场景
utf8 3 字节 基本多文种平面(BMP,U+0000~U+FFFF) 不能 无表情、无特殊符号的场景
utf8mb4 4 字节 全部 Unicode 字符(含 U+10000~U+10FFFF) 需存储表情、Emoji、特殊符号的场景
  • 关键结论utf8mb4 是 MySQL 中真正完整支持 UTF-8 编码的字符集,utf8 是不完整的子集(仅 3 字节)。

存储表情符号的完整解决方案

要在 MySQL 中正确存储表情符号,需从 字段、表、数据库 三个层级修改字符集为 utf8mb4,并确保连接层也使用该字符集。

修改字段的字符集(最关键)

直接修改存储表情的字段,指定 utf8mb4 字符集和对应的校对规则:

1
2
3
4
5
6
7
-- 语法:ALTER TABLE 表名 MODIFY 字段名 类型 CHARACTER SET utf8mb4 COLLATE 校对规则;
ALTER TABLE department
MODIFY name VARCHAR(120)
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci -- 校对规则(不区分大小写,支持 Unicode 排序)
NOT NULL DEFAULT ''
COMMENT '部门名称';
  • 校对规则选择:
    • utf8mb4_unicode_ci:遵循 Unicode 标准排序,支持多语言正确比较(推荐)。
    • utf8mb4_general_ci:排序规则简单,性能略高,但某些语言排序可能不准确。
    • utf8mb4_bin:二进制比较,区分大小写(如需要严格区分大小写时使用)。

可选:修改表的默认字符集

若表中多个字段需要存储表情,可修改表的默认字符集(新字段会继承该设置):

1
2
3
ALTER TABLE department 
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

可选:修改数据库的默认字符集

若整个数据库都需要支持表情,可修改数据库的默认字符集(新表会继承该设置):

1
2
3
ALTER DATABASE 数据库名 
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

配置连接层字符集

即使表和字段设置了 utf8mb4,若应用与 MySQL 的连接使用 utf8 字符集,仍会导致表情存储失败。需在连接字符串中指定 charset=utf8mb4

不同语言的连接配置示例:
  • Java(JDBC)

    1
    jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=UTC
  • Python(pymysql)

    1
    2
    3
    4
    5
    6
    7
    conn = pymysql.connect(
    host='localhost',
    user='root',
    password='123456',
    db='dbname',
    charset='utf8mb4' # 指定字符集
    )
  • PHP(PDO)

    1
    2
    3
    4
    5
    $pdo = new PDO(
    "mysql:host=localhost;dbname=dbname;charset=utf8mb4",
    "root",
    "123456"
    );

验证配置是否生效

1
2
3
4
5
6
7
8
-- 查看字段字符集
SHOW FULL COLUMNS FROM department WHERE Field = 'name';

-- 查看表字符集
SHOW CREATE TABLE department;

-- 查看数据库字符集
SHOW CREATE DATABASE 数据库名;

若输出中 Collationutf8mb4_unicode_ci(或其他 utf8mb4 系列校对规则),则配置生效。

注意事项

  1. 兼容性
    • utf8mb4 向下兼容 utf8,已存储的 3 字节字符无需转换,新增的 4 字节字符(表情)可正常存储。
    • MySQL 5.5.3 及以上版本支持 utf8mb4,若使用更低版本需升级。
  2. 性能影响
    • utf8mb4 存储 4 字节字符会比 utf8 多占用约 33% 的空间(对文本字段影响较大)。
    • 索引长度限制:VARCHAR(255)utf8mb4 时,索引最大长度为 255 * 4 = 1020 字节,若超过需缩短字段长度或修改 innodb_large_prefix 参数。
  3. 全链路一致性
    • 确保从 “应用 → 连接池 → MySQL 服务 → 字段” 的所有环节都使用 utf8mb4,任何一环使用 utf8 都会导致表情存储失败

欢迎关注我的其它发布渠道