MySQL插入emoji表情失败问题的解决方法

发布时间 - 2026-01-11 00:57:55    点击率:

前言

之前一直认为UTF-8是万能的字符集问题解决方案,直到最近遇到这个问题。最近在做新浪微博的爬虫, 在存库的时候发现只要保持emoji表情,就回抛出以下异常:

Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...'

众所周知UTF-8是3个字节, 其中已经包括我们日常能见过的绝大多数字体. 但3个字节远远不够容纳所有的文字, 所以便有了utf8mb4, utf8mb4是utf8的超集, 占4个字节, 向下兼容utf8. 我们日常用的emoji表情就是4个字节了.

所以在此我们像utf8的数据表插入数据就会报出Incorrect string value这个错误.

Google一下很容易就找到了解决方案, 具体解决办法是如下:

一、修改数据表的字符集为utf8mb4

这点很简单, 修改语句网上找一大堆, 不过建议重新建表, 使用 mysqldump -uusername -ppassword database_name table_name > table.sql 备份相应数据表, 并修改其中的建表语句的字符集为 utf8mb4 即可, 然后 mysql -uusername -ppassword database_name < table.sql 重新导入sql即可完成修改字符集操作.

二、MySQL数据库版本要5.5.3及以上

网络上所有的文章都说明要MySQL 5.5.3以上的版本才支持utf8mb4, 不过我使用的数据库版本为5.5.18, 最终仍能解决问题, 所以同学们不要急着找运维哥哥升级数据库先, 先试试能不能自己解决问题.

三、修改数据库配置文件/etc/my.cnf并重启mysql服务

主要是修改数据库的默认字符集, 以及连接, 查询的字符集, [Mysql支持emoji 表情符号 升级编码为UTF8MB4][1] 这篇文章有详细的设置方法, [深入Mysql字符集设置][2] 这篇文章有其中设置的各个字符集的作用, 大家可以科普下.

四、升级MySQL Connector到5.1.21及以上

以上所有的操作, 最关键的是步骤3, 修改数据库的配置文件, 其中大概修改了

[client]
# 客户端来源数据的默认字符集
default-character-set = utf8mb4
[mysqld]
# 服务端默认字符集
character-set-server=utf8mb4
# 连接层默认字符集
collation-server=utf8mb4_unicode_ci
[mysql]
# 数据库默认字符集
default-character-set = utf8mb4

这些配置指定了数据从客户端到服务端所经过的一条条管道使用的字符集, 其中每一个管道出现问题都可能会导致插入失败或者乱码.

但很多时候, 线上的数据库是不能随便修改数据库文件的, 所以我们的运维同学很果断的回绝了我修改数据库配置文件的请求(T_T)

所以就只能用代码解决了, 一开始是准备从JDBC连接时候就指定使用的字符集处下手.

jdbc:mysql://localhost:3306/ding?characterEncoding=UTF-8

主要把UTF-8修改为utf8mb4对于的Java Style Charset字符串应该就能解决问题吧?

不过很遗憾的是, Java JDBC并不存在utf8mb4对于的字符集. 使用UTF-8的时候可以兼容urf8mb4并自动转换字符集.

For example, to use 4-byte UTF-8 character sets with Connector/J, configure the MySQL server with character_set_server=utf8mb4, and leave characterEncoding out of the Connector/J connection string. Connector/J will then autodetect the UTF-8 setting. – [MySQL:Using Character Sets and Unicode][3]

后来科普了一下, 在每一次查询请求的时候, 可以显式的指定使用的字符集, 使用 set names utf8mb4 可以指定本次链接的字符集为utf8mb4, 但这个设置在每次连接被释放后都会失效.

目前的解决办法是, 在需要插入utf8mb4的时候, 显示地调用执行set names utf8mb4, 如:

jdbcTemplate.execute("set names utf8mb4");
jdbcTempalte.execute("...");

需要注意的是, 我们在使用一下ORM框架的时候, 因为性能优化原因, 框架会延迟提交, 除非事务结束或者用户主动调用强制提交, 负责执行的set names utf8mb4仍然不会生效.

在这里我使用的是myBatis, 以MessageDao为例

// MessageDao
public interface MessageDao {
 @Update("set names utf8mb4")
 public void setCharsetToUtf8mb4();
 @Insert("insert into tb_message ......")
 public void insert(Message msg);
}
// test code
SqlSession sqlSession = sqlSessioFactory.openSession();
messageDao = sqlSession.getMapper(MessageDao.class);
messageDao.setCharsetToUtf8mb4();
// 强制提交
sqlSession.commit();
messageDao.insert(message);

至此, 问题便解决了..

哎, 如果世事能那么顺利就好了, 在项目中, mybatis是实例是交由Spring去管理的, 也就是说我拿不到sqlSession, 也就是强制提交不了. 并且因为Spring事务框架的限制, 他并不允许用户显式调用强制提交. 目前还在纠结这个问题.

有两个解决思路:

  • 使用AOP, 在可能插入4字节UTF8字符的时候, 前置方法执行set names utf8mb4, 但该方案还不能确定AOP的方法会被Spring进行事务管理么, 并且在前置方法中,拿到的链接是否和接下来拿到的连接对象是同一个session.
  • 研究Spring JDBC的创建方法, 写一个hook在每次创建新的数据库连接的时候, 都执行一次set names utf8mb4, 这样就保证每一次拿到的链接都是设置过字符集的.

总结

以上就是这篇文章的全部内容了,待有时间再实验一下以上两种方案。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。


# mysql支持emoji表情  # mysql  # emoji表情  # 让mysql支持emoji表情  # mysql存储emoji表情步骤详解  # mysql中插入emoji表情失败的原因与解决  # MySQL无法存储emoji表情解决方案分析  # mysql存储emoji表情报错的处理方法【更改编码为utf8mb4】  # MySQL无法存储Emoji表情问题的解决方法分析  # 让Java后台MySQL数据库能够支持emoji表情的方法  # 使MySQL能够存储emoji表情字符的设置教程  # MySQL如何插入Emoji表情  # 的是  # 解决问题  # 这篇文章  # 配置文件  # 这个问题  # 解决办法  # 服务端  # 都是  # 解决了  # 就会  # 还在  # 就能  # 在这  # 在此  # 见过  # 两种  # 很容易  # 同学们  # 很简单  # 线上 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  如何在腾讯云免费申请建站?  Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  如何挑选优质建站一级代理提升网站排名?  Laravel如何使用Service Container和依赖注入?(代码示例)  如何挑选高效建站主机与优质域名?  Laravel如何创建自定义Artisan命令?(代码示例)  如何在建站之星绑定自定义域名?  Laravel Admin后台管理框架推荐_Laravel快速开发后台工具  EditPlus 正则表达式 实战(3)  小米17系列还有一款新机?主打6.9英寸大直屏和旗舰级影像  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  详解vue.js组件化开发实践  Laravel如何配置中间件Middleware_Laravel自定义中间件拦截请求与权限校验【步骤】  个人摄影网站制作流程,摄影爱好者都去什么网站?  详解Android中Activity的四大启动模式实验简述  Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程  简单实现jsp分页  微信小程序 input输入框控件详解及实例(多种示例)  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  网易LOFTER官网链接 老福特网页版登录地址  lovemo网页版地址 lovemo官网手机登录  b2c电商网站制作流程,b2c水平综合的电商平台?  专业商城网站制作公司有哪些,pi商城官网是哪个?  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  装修招标网站设计制作流程,装修招标流程?  深圳网站制作的公司有哪些,dido官方网站?  免费网站制作appp,免费制作app哪个平台好?  Laravel如何为API生成Swagger或OpenAPI文档  Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南  高防服务器租用指南:配置选择与快速部署攻略  移动端脚本框架Hammer.js  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  html5如何实现懒加载图片_ intersectionobserver api用法【教程】  Linux网络带宽限制_tc配置实践解析【教程】  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  Laravel如何配置和使用缓存?(Redis代码示例)  宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法  如何实现javascript表单验证_正则表达式有哪些实用技巧  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  如何在万网自助建站中设置域名及备案?  Laravel怎么自定义错误页面_Laravel修改404和500页面模板  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势