Skip to main content
  1. posts/

Java连接Mysql字符集设置过程详解

·1179 words·3 mins

现象

生产数据库设置了数据库的字符集为utf8mb4。数据库层面可以正常插入表情。但是在java程序中设置表情却不生效。 测试数据库也设置了数据库的字符集为utf8mb4。数据库层面可以正常插入表情。但是在java程序中也可以正常插入表情。

image.png
测试和生产环境的区别是:测试环境数据库重启过。生产没有==。 但是生产环境重启数据库影响太大,不太现实。 有没有什么其他的解决方案呢?请往下看。

先说结论,三种解决方案

  1. 重启数据库(character-set-server 这个配置只在数据库启动时生效)
  2. 修改连接配置,指定连接的字符集 (数据库连接后面加上 com.mysql.jdbc.faultInjection.serverCharsetIndex=45)
  3. 升级 mysql连接驱动到5.1.47之后的版本(因为这个版本之后设置encoding=utf8会自动映射成utf8mb4)

上个链接吧,完美解决。 https://blog.arstercz.com/mysql-connector-java-%E6%8F%92%E5%85%A5-utf8mb4-%E5%AD%97%E7%AC%A6%E5%A4%B1%E8%B4%A5%E9%97%AE%E9%A2%98%E5%A4%84%E7%90%86%E5%88%86%E6%9E%90/ 作者的思路很清晰。

对于修改连接配置这一点,有点奇怪的是, 我在本地连接数据库测试的时候,默认设置的字符集就是utf8mb4。 但是在预发环境抓连接mysql的包是,发现设置的字符集却是utf8。 上图!

但是代码一样的呀!没有理由会有不同啊。 于是开始了下面的探索,嘿嘿嘿。

java-mysql-connector和mysql建立连接的过程

Mysql握手协议包

java-mysql-connector设置字符集过程

### 一条SQL从客户端到服务器
详情建议阅读《高性能Mysql》第7.9章。

顺带又了解一些Mysql的字符集相关内容

1.字符集参数含义

2.mysql字符集相关sql

SQL含义
SET NAMES utf8mb4设置本次连接的字符集为utf8mb4
SELECT * FROM information_schema.COLLATIONS ;查看mysql排序规则
show variables like ‘%character%’;查看数据库字符集
show variables like ‘collation%’;查看数据库排序规则
alter database 库名 default character set utf8mb4;修改数据库字符集(character_set_database)
set character_set_server=utf8;设置服务器编码(character_set_server)

java-mysql-connector源码(简单记录一下,方便以后回顾)

主要是从类 ConnectionImpl 里面的 方法 configureClientCharacterSet 入手去追溯一下过程。 简单贴几个过程吧

初始设置字符集,
处理utf8和utf8mb4,

简单总结一下

mysql连接过程【看上图】 mysql设置字符集过程【看上图】 mysql字符集应该注意的问题

  1. 配置生效问题【有些配置可能要重启mysql服务器才能生效】
  2. 配置设置问题【java启动参数,环境变量,配置文件】

排查思路

  1. 对比现象【代码相同,开发和预发建立连接时,设置的字符集不同】
  2. 猜想问题【服务器返回结果不同,导致设置的字符集不同】
  3. 分析过程,验证猜想【从抓包分析,设置字符集前,先获取了一波服务器配置,对比分析配置。发现差不多,没什么不同】
  4. 根据现象,分析过程【既然是字符集设置不同,就看它字符集设置的过程。最终发现问题】
  5. 发现问题,寻找解决方案【修改字符集配置】