向 MySQL 更新数据时若遇到:

Incorrect string value: '\xF0\x9F\x98\x82\xEF\xBC...' for column 'content' at row 1

通常是因为字段字符集为 utf8,无法存储 emoji 表情,需要改为 utf8mb4

utf8 与 utf8mb4 的差别

  • MySQL 的 utf8 最多支持 3 字节编码,不是完整的 UTF-8。
  • utf8mb4 才能覆盖所有 Unicode 字符,包括 emoji。
  • 建议 MySQL 或 MariaDB 用户统一使用 utf8mb4

配置 utf8mb4

全局配置

若可修改数据库服务器配置,更新 MySQL 配置文件:

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
# 忽略客户端的字符集请求,强制使用服务器字符集返回结果
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

检查结果:

mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8mb4_unicode_ci |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)

单库配置

如无法调整服务器设置,可在数据库层指定:

  • 创建数据库时:
CREATE DATABASE dbname CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
  • 连接数据库时在连接串指定字符集:
mysql+[driver]://[username]:[password]@[host]:[port]/[dbname]?charset=utf8mb4

从 utf8 迁移至 utf8mb4

  1. 备份数据;
  2. 确认 MySQL 版本 ≥ 5.5.3;
  3. 修改数据库、表、字段字符集:
# 数据库
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

# 
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# varchar 字段
ALTER TABLE table_name CHANGE column_name column_name VARCHAR(xx) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  1. 检查索引长度是否超限,参考官方文档;
  2. 配置服务器字符集(见前文);
  3. 修复并优化表:
REPAIR TABLE table_name;
OPTIMIZE TABLE table_name;

或使用:

mysqlcheck -u root -p --auto-repair --optimize --all-databases

参考链接