LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

某次信創環境Oceanbase數據庫偶發亂碼問題

freeflydom
2025年2月7日 9:53 本文熱度 21

資料遷移,整理分享。 問題發生在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中指定字符集方式:

? 在創建租戶時設置字符集

o 可以在 create tenant 語句添加 charset 設置,添加 "charset=utf8"

o 可以在 OCP 中創建租戶時,選擇字符集為utf8

? 設置客戶端(鏈路)字符集

o 客戶端(鏈路)字符集是配置 client 和 server 之間交互使用的字符集設置

set global character_set_client = utf8;

set global character_set_connection = utf8;

set global character_set_results = utf8;

? 設置客戶端字符集

o 使用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

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
日韩欧美a∨中文字幕 | 日本久久综合久久综合 | 亚洲人成网在线播放观看 | 中文字幕国产视频 | 婷婷色婷婷开心五月 | 亚洲欧美中文字幕永久有效 |