LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

某次信创环境Oceanbase数据库偶发乱码问题

freeflydom
2025年2月7日 9:53 本文热度 25

资料迁移,整理分享。 问题发生在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_clientcharacter_set_connection是否乱码结果
utf8mb4utf8mb4 否
utf8mb4gbk




gbkgbk
gbkutf8mb4

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_clientcharacter_set_connection是否乱码结果
utf8mb4utf8mb4
utf8mb4gbk
gbkgbk
gbkutf8mb4

由上结果可证: 在mysql的innodb引擎下,当 character_set_client 的编码与请求端的实际编码方式不匹配时,会出现数据的乱码情况。

OceanBase测试用例一 :


 通过代码修改 当前数据库连接 的字符编码设置,修改前后重复执行  SELECT '中文字段啊四川省' as col FROM dual  语句,查看输出结果是否乱码。

character_se

t_client

character_se

t_connection

character_se

t_results

是否

乱码

结果
utf8mb4utf8mb4utf8mb4 否
utf8mb4utf8mb4gbk
utf8mb4gbkutf8mb4
utf8mb4gbkgbk





gbkutf8mb4utf8mb4
gbkutf8mb4gbk
gbkgbkutf8mb4
gbkgbkgbk

根据上方表格及输出截图发现,oceanbase中,character_set_connection与请求端编码一致时不会出现乱码的情况。

Oceanbase测试用例二:

字段,测试代码沿用mysql测试示例二中的内容,下方继续以表格形式展示:

character_se

t_client

character_se

t_connection

character_se

t_results

是否乱码结果
utf8mb4utf8mb4utf8mb4 否
utf8mb4utf8mb4gbk
utf8mb4gbkutf8mb4

无法确定。

默认配置插入一条数据后,切换为当前组合,第一或者第二条数据会乱码,后面出现较少

utf8mb4gbkgbk无法确定,得不到确切的规律,多次执行时甚至会间接出现乱码与不乱码的情况。





gbkutf8mb4utf8mb4
gbkutf8mb4gbk
gbkgbkutf8mb4无法确定,得不到确切的规律,多次执行时甚至会间接出现乱码与不乱码的情况
gbkgbkgbk无法确定,得不到确切的规律,多次执行时甚至会间接出现乱码与不乱码的情况请看下面的对比图

这里有一个很奇怪的地方是:

直 接运行 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初始化征信接口使用的数据库连接,避免与框架使用的数据库连接池冲突。

​转自https://www.cnblogs.com/imzx/p/18688135


该文章在 2025/2/7 9:53:26 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved