记录一次emoji写入到数据库发生的错误

问题描述

我在一个Web项目中,文本(content)加入了emoji的功能。

就像这样:😁👍😇

然后在调用后端接口中,报错了。

Error 3988 (HY000): Conversion from collation utf8mb3_general_ci into utf8mb4_0900_ai_ci impossible for parameter

知识点

  1. 字符集与排序规则
    • MySQL 使用字符集(charset)来定义存储的文本编码格式,最常见的是 utf8utf8mb4
    • utf8 是较旧的 UTF-8 编码格式,支持最多 3 字节的 Unicode 字符。(使用utf8默认为 utf8mb3(UTF-8 MultiByte 3-byte)!)
    • utf8mb4 是更新的 UTF-8 编码格式,支持最多 4 字节的 Unicode 字符,包括 Emoji 在内的所有 Unicode 字符。
  2. Emoji 和 UTF-8
    • Emoji 是 Unicode 字符的一部分,一些 Emoji 字符需要 4 字节才能正确存储和处理,因此需要使用 utf8mb4 字符集。

问题根因:

  • 数据库表的字符集和排序规则未正确配置为 utf8mb4,而是使用了较旧的 utf8
  • 当尝试向 utf8 字符集的表插入包含 Emoji 的文本时,MySQL 无法将 utf8mb3 转换为 utf8mb4,因为 utf8mb3 不支持 Emoji 和其他 4 字节的 Unicode 字符。

代码

在初始化数据库时代码需要改动:

	driverName := "mysql"
	user := "root"
	password := "123456"
	host := "localhost"
	port := "3306"
	database := "MyDatabase"
	charset := "utf8mb4" // charset := "utf8" 是默认 utf8mb3 !
	loc := "Asia/Shanghai"
	args := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=%s&parseTime=true&loc=%s",
		user,
		password,
		host,
		port,
		database,
		charset,
		url.QueryEscape(loc))
	db, err := gorm.Open(driverName, args)

另外在数据库定义:

  • 数据库schema

  • 确保数据库使用的字符集和排序规则是 utf8mb4

    • 通过修改表的 COLLATE 属性来实现,例如:ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
  • 修改具体字段的字符集:

    • CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci
posted @ 2024-06-20 00:43  江水为竭  阅读(78)  评论(0编辑  收藏  举报