某次信創(chuàng)環(huán)境Oceanbase數(shù)據(jù)庫偶發(fā)亂碼問題
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
資料遷移,整理分享。 問題發(fā)生在2023年 一、環(huán)境介紹及問題簡述
在客戶方搭建的信創(chuàng)環(huán)境中,使用麒麟Linux作為操作系統(tǒng),Oceanbase作為應(yīng)用數(shù)據(jù)庫,東方通TongWeb作為Web應(yīng)用容器,在此環(huán)境下 部署我司JAVA應(yīng)用(后續(xù)表述中將使用簡稱WebA),在WebA使用過程中,偶發(fā)的出現(xiàn)中文字符入庫后亂碼的問題,導(dǎo)致業(yè)務(wù)數(shù)據(jù)無法正常查看。 其中,oceanbase數(shù)據(jù)庫編碼使用GBK,TongWeb中HTTP通道也使用了默認(rèn)的GBK編碼,WebA則采用UTF8編碼,應(yīng)用與數(shù)據(jù)庫的連接,交由TongWeb中的數(shù)據(jù)源配置進(jìn)行池化管理。 該亂碼問題隨機(jī)出現(xiàn),無規(guī)律,時(shí)間隨機(jī),針對(duì)同一個(gè)功能,即便是相同的數(shù)據(jù),也不會(huì)重復(fù)觸發(fā)。 二、結(jié)論聲明
三、原因解釋1、作為前提,需要知道,每一種編碼方式會(huì)有自己的字符映射表。同樣的字節(jié)序列在不同的編碼方式中代表的是不同的字符。 2、在向數(shù)據(jù)庫服務(wù)器發(fā)送一條SQL指令時(shí),指令及指令中的數(shù)據(jù)是以字節(jié)序列的形式發(fā)送到后臺(tái)的。 3、在數(shù)據(jù)庫中,可以通過 show variables like '%char%' 命令獲取當(dāng)前連接下的數(shù)據(jù)庫編碼,如下圖 其中,character_set_client 是數(shù)據(jù)庫服務(wù)器認(rèn)為的請(qǐng)求端使用的字符編碼方式,如上圖,即便客戶端在發(fā)送sql語句時(shí),使用的是GBK編碼,服務(wù)器也會(huì)將其認(rèn)為是UTF8編碼進(jìn)行處理。 character_set_connection 數(shù)據(jù)庫服務(wù)器會(huì)把按照 character_set_client 編碼處理的字符再轉(zhuǎn)換為 character_set_connection 對(duì)應(yīng)的編碼方案。此時(shí),如果兩者的配置值相同,就可以省略一個(gè)轉(zhuǎn)換的操作。 服務(wù)器的后續(xù)操作中,還會(huì)發(fā)生 character_set_connection到數(shù)據(jù)庫表或數(shù)據(jù)表列的字符轉(zhuǎn)換。 character_set_results 是服務(wù)器向請(qǐng)求端返回?cái)?shù)據(jù)時(shí)使用的字符集,服務(wù)器會(huì)采用該變量指定的字符集對(duì)返回給客戶端的數(shù)據(jù)進(jìn)行編碼。 針對(duì)入庫亂碼的問題,此處重點(diǎn)關(guān)注 character_set_client 與 character_set_connection 4、set names gbk的作用 該 語句將三個(gè)會(huì)話系統(tǒng)變 量 character_set_client , character_set_connection 和 character_set_results 設(shè)置為給定的GBK字符集。 該命令僅作用于當(dāng)前數(shù)據(jù)庫會(huì)話,SESSION級(jí)別,詳情見SET NAMES_用戶指南_云數(shù)據(jù)庫OceanBase_敏捷版通用版本 (aliyun.com)。 另外,在OB數(shù)據(jù)中,支持在租戶級(jí)、Database 級(jí)、表級(jí)、字段級(jí)、session 級(jí)設(shè)置字符集,詳見字符集規(guī)范-OceanBase 數(shù)據(jù)庫 -OceanBase文檔中心-分布式數(shù)據(jù)庫使用文檔 5、測(cè)試(MySQL環(huán)境,OceanBase環(huán)境)。 MySQL測(cè)試用例一 :
MySQL測(cè)試用例二: 定義如下數(shù)據(jù)庫表
修改 當(dāng)前數(shù)據(jù)庫連接 的字符編碼設(shè)置,執(zhí)行insert插入語句,查看插入的數(shù)據(jù)是否亂碼。
由上結(jié)果可證: 在mysql的innodb引擎下,當(dāng) character_set_client 的編碼與請(qǐng)求端的實(shí)際編碼方式不匹配時(shí),會(huì)出現(xiàn)數(shù)據(jù)的亂碼情況。 OceanBase測(cè)試用例一 :
根據(jù)上方表格及輸出截圖發(fā)現(xiàn),oceanbase中,character_set_connection與請(qǐng)求端編碼一致時(shí)不會(huì)出現(xiàn)亂碼的情況。 Oceanbase測(cè)試用例二:字段,測(cè)試代碼沿用mysql測(cè)試示例二中的內(nèi)容,下方繼續(xù)以表格形式展示:
這里有一個(gè)很奇怪的地方是: 直 接運(yùn)行 set character_set_client = gbk, character_set_connection = gbk, character_set_results = gbk, 然后執(zhí)行插入,有時(shí)可以得到正常數(shù)據(jù),有時(shí)候又是亂碼的數(shù)據(jù)。 運(yùn)行 set names gbk后執(zhí)行插入,則可以穩(wěn)定觸發(fā)亂碼現(xiàn)象。下方為對(duì)比圖: 根據(jù)以上測(cè)試結(jié)果發(fā)現(xiàn),在oceanbase中當(dāng) character_set_connection 的編碼與請(qǐng)求端的實(shí)際編碼方式不匹配時(shí),會(huì)出現(xiàn)數(shù)據(jù)的亂碼情況,且該亂碼情況也是隨機(jī)出現(xiàn),無法確認(rèn)規(guī)律。 四、使用建議1、 建議將 character_set_client , character_set_connection 和 character_set_results 都設(shè)置為應(yīng)用使用的編碼方式,在WebA應(yīng)用的環(huán)境下使用時(shí),應(yīng)該將參數(shù)默認(rèn)設(shè)置為 utf8mb4。具體設(shè)置方式請(qǐng)參考:
五、當(dāng)前采用的修復(fù)方案1、使用jdbc初始化征信接口使用的數(shù)據(jù)庫連接,避免與框架使用的數(shù)據(jù)庫連接池沖突。 ?轉(zhuǎn)自https://www.cnblogs.com/imzx/p/18688135 該文章在 2025/2/7 9:53:26 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |