某次信创环境Oceanbase数据库偶发乱码问题
资料迁移,整理分享。 问题发生在2023年
一、环境介绍及问题简述
| 数据库 | oceanbase |
| 操作系统 | Linux (麒麟) |
| WEB中间件 | Tongweb |
| 数据库表编码 | GBK |
| 中间件默认使用的HTTP通道编码 | GBK |
| 金仕达Java应用 | UTF8 |
在客户方搭建的信创环境中,使用麒麟Linux作为操作系统,Oceanbase作为应用数据库,东方通TongWeb作为Web应用容器,在此环境下 部署我司JAVA应用(后续表述中将使用简称WebA),在WebA使用过程中,偶发的出现中文字符入库后乱码的问题,导致业务数据无法正常查看。
其中,oceanbase数据库编码使用GBK,TongWeb中HTTP通道也使用了默认的GBK编码,WebA则采用UTF8编码,应用与数据库的连接,交由TongWeb中的数据源配置进行池化管理。
该乱码问题随机出现,无规律,时间随机,针对同一个功能,即便是相同的数据,也不会重复触发。
二、结论声明
- 排查后发现,现场存在定制化功能,对外公布接口,该接口在收到请求后,会调用set names gbk这个数据库命令以防止后续SP执行返回中文乱码。
- 该命令会修改数据库session级的字符编码,而且WebA的数据库连接是由中间件池化管理的,进而导致连接池里的连接被 set names gbk 命令污染。
- WebA采用的字符集又是UTF8,后续使用过程中,使用被污染的连接操作中文字符时就会出现乱码问题。
三、原因解释
1、作为前提,需要知道,每一种编码方式会有自己的字符映射表。同样的字节序列在不同的编码方式中代表的是不同的字符。
2、在向数据库服务器发送一条SQL指令时,指令及指令中的数据是以字节序列的形式发送到后台的。
3、在数据库中,可以通过 show variables like '%char%' 命令获取当前连接下的数据库编码,如下图

其中,character_set_client 是数据库服务器认为的请求端使用的字符编码方式,如上图,即便客户端在发送sql语句时,使用的是GBK编码,服务器也会将其认为是UTF8编码进行处理。
character_set_connection 数据库服务器会把按照 character_set_client 编码处理的字符再转换为 character_set_connection 对应的编码方案。此时,如果两者的配置值相同,就可以省略一个转换的操作。
服务器的后续操作中,还会发生 character_set_connection到数据库表或数据表列的字符转换。
character_set_results 是服务器向请求端返回数据时使用的字符集,服务器会采用该变量指定的字符集对返回给客户端的数据进行编码。
针对入库乱码的问题,此处重点关注 character_set_client 与 character_set_connection
4、set names gbk的作用
该 语句将三个会话系统变 量 character_set_client , character_set_connection 和 character_set_results 设置为给定的GBK字符集。 该命令仅作用于当前数据库会话,SESSION级别,详情见SET NAMES_用户指南_云数据库OceanBase_敏捷版通用版本 (aliyun.com)。

另外,在OB数据中,支持在租户级、Database 级、表级、字段级、session 级设置字符集,详见字符集规范-OceanBase 数据库 -OceanBase文档中心-分布式数据库使用文档
5、测试(MySQL环境,OceanBase环境)。
MySQL测试用例一 :
在WebA中通过代码修改 当前数据库连接 的字符编码设置,修改前后重复执行 SELECT '中文字段啊四川省' as col FROM dual 语句,查看输出结果是否乱码。
| character_set_client | character_set_connection | 是否乱码 | 结果 |
| utf8mb4 | utf8mb4 | 否 | ![]() |
| utf8mb4 | gbk | 否 | ![]() |
| gbk | gbk | 是 | ![]() |
| gbk | utf8mb4 | 是 | ![]() |
MySQL测试用例二:
定义如下数据库表
CREATE TABLE encoding_test (
zzz varchar(100) DEFAULT NULL,
xxx varchar(100) DEFAULT NULL,
ccc varchar(100) DEFAULT NULL,
vvv varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk
修改 当前数据库连接 的字符编码设置,执行insert插入语句,查看插入的数据是否乱码。

| character_set_client | character_set_connection | 是否乱码 | 结果 |
| utf8mb4 | utf8mb4 | 否 |
|
| utf8mb4 | gbk | 否 | ![]() |
| gbk | gbk | 是 | ![]() |
| gbk | utf8mb4 | 是 | ![]() |
由上结果可证: 在mysql的innodb引擎下,当 character_set_client 的编码与请求端的实际编码方式不匹配时,会出现数据的乱码情况。
OceanBase测试用例一 :
通过代码修改 当前数据库连接 的字符编码设置,修改前后重复执行 SELECT '中文字段啊四川省' as col FROM dual 语句,查看输出结果是否乱码。
|
character_se t_client |
character_se t_connection |
character_se t_results |
是否 乱码 |
结果 |
| utf8mb4 | utf8mb4 | utf8mb4 | 否 |
![]() |
| utf8mb4 | utf8mb4 | gbk | 否 |
![]() |
| utf8mb4 | gbk | utf8mb4 | 是 |
![]() |
| utf8mb4 | gbk | gbk | 是 |
![]() |
| gbk | utf8mb4 | utf8mb4 | 否 |
![]() |
| gbk | utf8mb4 | gbk | 否 |
![]() |
| gbk | gbk | utf8mb4 | 是 |
![]() |
| gbk | gbk | gbk | 是 |
![]() |
根据上方表格及输出截图发现,oceanbase中,character_set_connection与请求端编码一致时不会出现乱码的情况。
Oceanbase测试用例二:
字段,测试代码沿用mysql测试示例二中的内容,下方继续以表格形式展示:
|
character_se t_client |
character_se t_connection |
character_se t_results |
是否乱码 | 结果 |
| utf8mb4 | utf8mb4 | utf8mb4 | 否 |
![]() |
| utf8mb4 | utf8mb4 | gbk | 否 | |
| utf8mb4 | gbk | utf8mb4 |
无法确定。 默认配置插入一条数据后,切换为当前组合,第一或者第二条数据会乱码,后面出现较少 |
![]() |
| utf8mb4 | gbk | gbk | 无法确定,得不到确切的规律,多次执行时甚至会间接出现乱码与不乱码的情况。 |
![]() |
| gbk | utf8mb4 | utf8mb4 | 否 |
![]() |
| gbk | utf8mb4 | gbk | 否 |
![]() |
| gbk | gbk | utf8mb4 | 无法确定,得不到确切的规律,多次执行时甚至会间接出现乱码与不乱码的情况 |
![]() |
| gbk | gbk | gbk | 无法确定,得不到确切的规律,多次执行时甚至会间接出现乱码与不乱码的情况 | 请看下面的对比图 |
这里有一个很奇怪的地方是:
直 接运行 set character_set_client = gbk, character_set_connection = gbk, character_set_results = gbk, 然后执行插入,有时可以得到正常数据,有时候又是乱码的数据。


运行 set names gbk后执行插入,则可以稳定触发乱码现象。下方为对比图:
根据以上测试结果发现,在oceanbase中当 character_set_connection 的编码与请求端的实际编码方式不匹配时,会出现数据的乱码情况,且该乱码情况也是随机出现,无法确认规律。
四、使用建议
1、 建议将 character_set_client , character_set_connection 和 character_set_results 都设置为应用使用的编码方式,在WebA应用的环境下使用时,应该将参数默认设置为 utf8mb4。具体设置方式请参考:
部署在oceanbase上需要注意字符集规范,oceanbase默认字符集为utf-8, 无特殊需求无需修改。
oceanbase中指定字符集方式:
• 在创建租户时设置字符集
º 可以在 create tenant 语句添加 charset 设置,添加 "charset=utf8"
º 可以在 OCP 中创建租户时,选择字符集为utf8
• 设置客户端(链路)字符集
º 客户端(链路)字符集是配置 client 和 server 之间交互使用的字符集设置
set global character_set_client = utf8;
set global character_set_connection = utf8;
set global character_set_results = utf8;
• 设置客户端字符集
º 使用jdbc 连接 OceanBase 数据库,utf8 链路一般在 url 里修改参数设置,添加 characterEncoding=utf8
String url = "jdbc:oceanbase://xxx.xxx.xxx.xxx:xxxx?useSSL=false&useUnicode=true&characterEncoding=utf8&connectTimeout=30000&rewriteBatchedStatements=true";
客户端和服务端字符集编码要保持一致。
五、当前采用的修复方案
1、使用jdbc初始化征信接口使用的数据库连接,避免与框架使用的数据库连接池冲突。
某次信创环境Oceanbase数据库偶发乱码问题的更多相关文章
- 信创要求下,FTP要不要替代?要怎么进行国产化替代?
信创在国内如火如荼地发展,无论在技术探索和突破上,还是在政策规划上,都朝着更加完善的方向大步迈进.信创目前在从大的方面来说,信创目前主要集中在基础软件.硬件和芯片上,其中基础软件包括操作系统.数据库. ...
- OceanBase数据库实践入门——手动搭建OceanBase集群
前言 目前有关OceanBase功能.案例.故事的文章已经很多,对OceanBase感兴趣的朋友都想安装一个数据库试试.本文就是分享初学者如何手动搭建一个OceanBase集群.这也是学习理解Ocea ...
- 广州市首批!Smartbi入库信创产品资源池,引领国产BI软件崛起
为贯彻落实软件高质量发展战略,加快建设有影响力的信息技术创新(简称"信创")资源池,广州市工业和信息化局经征集申报.专家评审.现场考察等多个环节,发布了"广州市信息技术应 ...
- iPhone 6 被盗记录二【写在315前夕:苹果售后福州直信创邺在没有三包的情况下帮小偷翻新、助力小偷换机销赃!无视王法。让人震惊,痛心,憎恨!消费者很受伤很无奈】
投诉公司: 北京直信创邺数码科技有限公司 标题: 写在315前夕:苹果售后在没有三包的情况下帮小偷翻新.助力小偷换机销赃!无视王法.让人震惊,痛心,憎恨!消费者很受伤很无奈 期望: 还我手机,或者赔 ...
- 一键强制修改任意Mysql数据库的密码,修改任意环境Mysql数据库。
本文采用我软件里面的内置改密功能,可以一键强制修改Mysql数据库的密码, 在修改过程中,会强制干掉Mysql主程序,修改完成后重新启动Mysql就可以了. 首先讲解如何一键强制修改PHPWAMP自身 ...
- SQL Server中使用数据库快照的方式来完成测试环境中数据库的轻量级备份还原操作
在开发或者测试环境的数据库中,经常会发现有开发或者测试人员误删除表或者数据的情况,对于开发或者测试库,一般都没有安排定时的备份任务去备份数据库,一方面是由于存储资源有限,不太可能给开发或者测试环境准备 ...
- 生产环境MySQL数据库集群MHA上线实施方案
生产环境MySQL数据库集群MHA上线实施方案 一.不停库操作 1.在所有节点安装MHAnode所需的perl模块(需要有安装epel源) yum install perl-DBD-MySQL -y ...
- 【码上开心】Windows环境mysql数据库使用(二)skip-grant-tables 与用户名密码修改
skip-grant-tables #跳过数据库权限验证 我们安装MySql 设置my.ini配置文件的时候,常常会在my.ini中添加 skip-grant-tables ,这时接数据库可以使用任意 ...
- .NET 在信创常用软件适配清单之中?
2020年8月份写了一篇文章<.NET Core也是国产化信息系统开发的重要选项>, 这又过去了大半年了,在信创领域发生了很大的变化,今天写这篇文章主要是想从信创常用软件适配清单 看一看. ...
- 信创国产化,试试 Solon v2.2.2
Solon 是一个高效的 Java 应用开发框架:更快.更小.更简单.它不是 Spring.没有用 Servlet.也无关 JavaEE,是一个有自己接口标准的开放生态.可以为应用软件国产化提供支持, ...
随机推荐
- mkdir递归创建文件夹
mkdir -p 能递归创建文件夹 mkdir 只能创建一级文件夹,如果父文件夹不存在 则报错,所以如果你想用一个很确定的路径 在SHELL脚本里面可以直接写 mkdir -p /home/log/ ...
- 深度探讨Java字节代码的操纵方法
本文为IBM工程师成富编写的<Java深度历险>的第一部分Java字节代码的操纵,像这样Java语言的深度理解和运用还没有很多文章,我们把他奉献给读者,希望读者们喜欢. AD:2013云计 ...
- Blazor 组件库 BootstrapBlazor 中Row组件介绍
组件介绍 在Bootstrap中,我们经常使用row和col通过栅格化来控制显示位置. 如 <div class="row"> <div class=" ...
- Jx.Cms开发笔记(三)-Views主题动态切换
效果展示 我们可以在后台动态切换主题 目前Jx.Cms有两个主题,其中一个是默认主题,另一个是仿的Blogs主题. 我们可以通过点击启用按钮来动态切换两个主题. 实现方法 首先写一个实现IViewLo ...
- seldom-platform颠覆传统的自动化测试平台
1. 传统的自动化测试平台 近些年,中等以上规模的公司测试团队都在建设自己的自动化测试平台.主要要以 HTTP接口测试 和 性能测试 为主:一些平台还支持 Web UI测试和App UI测试等,试图通 ...
- 【ElementPlus】el-form使用技巧:动态切换校验规则的最佳实践
喵~ 今天分享一篇在 ElementPlus 中使用 el-form 动态切换校验规则 的实用方法. 一.问题概述 作为前端开发人员,在开发项目中,特别是后台管理系统,表单的使用是必不可少的.当业务需 ...
- C# Redis 的基本使用
C# Redis 的基本使用 -迷恋自留地 Redis 概述 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一 ...
- electron项目build报资源包下载出错
前情 公司有个桌面端项目是基于Electron开发的. 坑 上一次遇到npm install时安装electron无法安装,通过配置.npmrc文件解决了,今天在在执行npm run build的时候 ...
- ProcessExplorer 多功能任务管理器软件-中文绿色单文件版
今天我和大家分享一款系统监控工具--ProcessExplorer.一个比Windows自带的任务管理器更强大的工具.感觉最实用的是他的搜索功能,可以搜到系统任务管理器里面无法显示的应用, 大家可以网 ...
- SpringBoot 整合Swagger2 踩坑记录
SpringBoot 整合Swagger2 踩坑记录 Failed to start bean 'documentationPluginsBootstrapper'; nested exception ...




















