使用 nodejs 写入mysql 错误 nodejs mysql Incorrect string value


出现的场景时是,在抓包opensea 数据的时候, NFT 的 description 常常会有很多emoji 表情字符,碰到了错误
这种问题其实很常见,但是引起的原因却可能有多种。如果去google,最常见的回答是数据库的编码问题。也就是说,mysql 的 utf8 编码格式 其实是 utf8mb3, 只用 3 个字节存储字符,在尝试写入 emoji 表情的时候,需要用到4个字节来存储emoji表情。所以就会在写入时报这个错误 Incorrect string value。

step1:

查看自己的数据库编码格式
show create table assets
控制台将会返回类似的:
CREATE TABLE `assets` (
  `id` int NOT NULL AUTO_INCREMENT,
  ...
  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
结果显而易见,我的数据库本身就是 utf8mb4 格式的。照理来说不应该报这个错误。尝试自己手动写入数据
INSERT INTO assets description values ('🗿')
提示成功

step2:

由此可见,错误并不在数据库这边,那么就只有一种可能,nodejs在和数据库交互时数据链接出现了问题。本项目使用的是express框架,连接所用的为 mysql 库。很有可能是使用的这个 mysql 库与数据库连接的时候除了问题。
查看mysql的源码,可以找到option里有个配置字符串的配置项,位于

node_modules/mysql/lib/ConnectionConfig.js

于是,尝试在初始化连接配置项里,加上

charset: 'utf8mb4'

,再次尝试写入emoji,提示成功。
tips:
- 很多时候分析问题,看源码或许要方便的多。
- 如果发现自己的数据库编码不正确,可以尝试修改
ALTER TABLE assets CHANGE description description TEXT CHARACTER set UTF8MB4;
ALTER TABLE assets DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;