Java连接Mysql字符集设置过程详解
Table of Contents
现象
生产数据库设置了数据库的字符集为utf8mb4。数据库层面可以正常插入表情。但是在java程序中设置表情却不生效。 测试数据库也设置了数据库的字符集为utf8mb4。数据库层面可以正常插入表情。但是在java程序中也可以正常插入表情。测试和生产环境的区别是:测试环境数据库重启过。生产没有==。 但是生产环境重启数据库影响太大,不太现实。 有没有什么其他的解决方案呢?请往下看。
先说结论,三种解决方案
- 重启数据库(character-set-server 这个配置只在数据库启动时生效)
- 修改连接配置,指定连接的字符集 (数据库连接后面加上 com.mysql.jdbc.faultInjection.serverCharsetIndex=45)
- 升级 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字符集应该注意的问题
- 配置生效问题【有些配置可能要重启mysql服务器才能生效】
- 配置设置问题【java启动参数,环境变量,配置文件】
排查思路
- 对比现象【代码相同,开发和预发建立连接时,设置的字符集不同】
- 猜想问题【服务器返回结果不同,导致设置的字符集不同】
- 分析过程,验证猜想【从抓包分析,设置字符集前,先获取了一波服务器配置,对比分析配置。发现差不多,没什么不同】
- 根据现象,分析过程【既然是字符集设置不同,就看它字符集设置的过程。最终发现问题】
- 发现问题,寻找解决方案【修改字符集配置】