1.1 Oracle字符集問(wèn)題總結(jié)
1.1.1 oracle字符集概念
oracle字符集是一個(gè)字節(jié)數(shù)據(jù)的解釋的符號(hào)集合,有大小之分,有相互的包容關(guān)系。ORACLE 支持國(guó)家語(yǔ)言的體系結(jié)構(gòu)允許你使用本地化語(yǔ)言來(lái)存儲(chǔ),處理,檢索數(shù)據(jù)。它使數(shù)據(jù)庫(kù)工具,錯(cuò)誤消息,排序次序,日期,時(shí)間,貨幣,數(shù)字,和日歷自動(dòng)適應(yīng)本地化語(yǔ)言和平臺(tái)。
影響oracle數(shù)據(jù)庫(kù)字符集最重要的參數(shù)是NLS_LANG參數(shù)。格式:NLS_LANG = language_territory.charset
其中:Language 指定服務(wù)器消息的語(yǔ)言,territory 指定服務(wù)器的日期和數(shù)字格式,charset 指定字符集。如:AMERICAN _ AMERICA. ZHS16GBK。從NLS_LANG的組成我們可以看出,真正影響數(shù)據(jù)庫(kù)字符集的其實(shí)是第三部分。所以?xún)蓚€(gè)數(shù)據(jù)庫(kù)之間的字符集只要第三部分一樣就可以相互導(dǎo)入導(dǎo)出數(shù)據(jù),前面影響的只是提示信息是中文還是英文。
1.1.2 查詢(xún)Oracle的字符集
在做數(shù)據(jù)導(dǎo)入的時(shí)候,需要這三個(gè)字符集都一致:一是oracel server端的字符集,二是oracle client端的字符集;三是dmp文件的字符集。
A. 查詢(xún)oracle server端的字符集
SQL>select userenv('language') from dual;
結(jié)果類(lèi)似:AMERICAN_AMERICA.ZHS16GBK
或者select * from V$_NLS_PARAMETERS
B. 如何查詢(xún)dmp文件的字符集
dmp文件的第2和第3個(gè)字節(jié)記錄了dmp文件的字符集。小dmp文件用UltraEdit打開(kāi)(16進(jìn)制方式),看第2第3個(gè)字節(jié)的內(nèi)容,如0354,然后用以下SQL查出它對(duì)應(yīng)的字符集:
SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;
結(jié)果ZHS16GBK
dmp文件很大如2G以上,用文本編輯器打開(kāi)很慢或者完全打不開(kāi),可以用命令(在unix主機(jī)上):
cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6
然后用上述SQL也可以得到它對(duì)應(yīng)的字符集。
C. 查詢(xún)oracle client端的字符集
windows注冊(cè)表里面相應(yīng)OracleHome的NLS_LANG(如果裝配置臺(tái)等將總共有3個(gè):ORACLE下一個(gè)、ID0下有一個(gè)、HOME0下一個(gè))。還可以在dos窗口里面自己設(shè)置,如:set nls_lang=SIMPLIFIED CHINESE_CHINA.ZHS16GBK這樣就只影響這個(gè)窗口里面的環(huán)境變量;
在unix平臺(tái)下,就是環(huán)境變量NLS_LANG。$echo $NLS_LANG 如AMERICAN_AMERICA.ZHS16GBK
如果檢查的結(jié)果發(fā)現(xiàn)server端與client端字符集不一致,請(qǐng)統(tǒng)一修改為同server端相同的字符集(建議導(dǎo)入時(shí)直接在服務(wù)器上導(dǎo)入)
1.1.3 修改oracle的字符集
oracle的字符集有互相的包容關(guān)系。如us7ascii就是zhs16gbk的子集,從us7ascii到zhs16gbk不會(huì)有數(shù)據(jù)解釋上的問(wèn)題,不會(huì)有數(shù)據(jù)丟失。在所有的字符集中utf8應(yīng)該是最大,因?yàn)樗趗nicode,雙字節(jié)保存字符(也因此在存儲(chǔ)空間上占用更多)。
一旦數(shù)據(jù)庫(kù)創(chuàng)建后,數(shù)據(jù)庫(kù)的字符集理論上講是不能改變的。字符集的轉(zhuǎn)換是從子集到超集受支持,反之不行。如果兩種字符集之間根本沒(méi)有子集和超集的關(guān)系,那么字符集的轉(zhuǎn)換是不受oracle支持的。一般來(lái)說(shuō),除非萬(wàn)不得已,我們不建議修改oracle數(shù)據(jù)庫(kù)server端的字符集。特別說(shuō)明,我們最常用的兩種字符集ZHS16GBK和ZHS16CGB231280之間不存在子集和超集關(guān)系,因此理論上講這兩種字符集之間的相互轉(zhuǎn)換不受支持。
A. 修改server端字符集(不建議使用)
在oracle 8之前,可以用直接修改數(shù)據(jù)字典表props$來(lái)改變數(shù)據(jù)庫(kù)的字符集。但oracle8之后,至少有三張系統(tǒng)表記錄了數(shù)據(jù)庫(kù)字符集的信息,只改props$表并不完全,可能引起嚴(yán)重的后果。正確的修改方法如下:
$sqlplus /nolog
SQL>conn / as sysdba;
若此時(shí)數(shù)據(jù)庫(kù)服務(wù)器已啟動(dòng),則先執(zhí)行SHUTDOWN IMMEDIATE命令關(guān)閉數(shù)據(jù)庫(kù)服務(wù)器,然后執(zhí)行以下命令:
SQL>STARTUP MOUNT;
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK;
SQL>SHUTDOWN IMMEDIATE;
SQL>STARTUP
B. 修改dmp文件字符集
dmp文件的第2第3字節(jié)記錄了字符集信息,因此直接修改dmp文件的第2第3字節(jié)的內(nèi)容就可以'騙'過(guò)oracle的檢查。這樣做理論上也僅是從子集到超集可以修改,但很多情況下在沒(méi)有子集和超集關(guān)系的情況下也可以修改,我們常用的一些字符集,如US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK基本都可以改。因?yàn)楦牡闹皇莇mp文件,所以影響不大。
具體的修改方法比較多,最簡(jiǎn)單的就是直接用UltraEdit修改dmp文件的第2和第3個(gè)字節(jié)。比如想將dmp文件的字符集改為ZHS16GBK,可以用以下SQL查出該種字符集對(duì)應(yīng)的16進(jìn)制代碼:
SQL> select to_char(nls_charset_id('ZHS16GBK'), 'xxxx') from dual;
0354
然后將dmp文件的2、3字節(jié)修改為0354即可。
RAC環(huán)境修改oracle字符集
2.1 RAC環(huán)境存在問(wèn)題
在RAC環(huán)境下修改oracle服務(wù)器的字符集仍然按非RAC模式方法修改過(guò)程會(huì)遇到ORA-12720的錯(cuò)誤信息
SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
ORA-12720:, operation requires database is in EXCLUSIVE mode. Cause:,
上述錯(cuò)誤信息標(biāo)明在RAC方式下無(wú)法對(duì)服務(wù)端字符集進(jìn)行修改,需要將數(shù)據(jù)庫(kù)運(yùn)行在但實(shí)例模式運(yùn)行。
2.2 解決該問(wèn)題的嘗試
為解決上述遇到的問(wèn)題,嘗試將兩臺(tái)機(jī)器cluster軟件停止,在單節(jié)點(diǎn)上手工激活VG并啟動(dòng)oracle,又會(huì)遇到ORA-32700的錯(cuò)誤。錯(cuò)誤信息如下:
ora-32700 error occurred in DIAG Group Service
在很多情況下都會(huì)報(bào)ORA-32700的錯(cuò)誤,在此處的原因大概是因?yàn)闆](méi)有啟動(dòng)雙機(jī)cluster軟件導(dǎo)致,如果將單節(jié)點(diǎn)的cluster進(jìn)程啟動(dòng),oracle實(shí)例也會(huì)跟著啟動(dòng),修改時(shí)又會(huì)出現(xiàn)2.1節(jié)遇到的錯(cuò)誤。
2.3 RAC環(huán)境修改字符集步驟
2.3.1 數(shù)據(jù)庫(kù)參數(shù)文件目錄備份
為解決2.1節(jié)遇到錯(cuò)誤就必須將數(shù)據(jù)庫(kù)修改為單實(shí)例非cluster模式,需要對(duì)數(shù)據(jù)庫(kù)參數(shù)文件進(jìn)行修改,但進(jìn)行參數(shù)文件修改需要一些竅門(mén)和方法。
正常RAC模式下ORACLE_HOME/dbs目錄下文件如下列表
-rw-r--r-- 1 oracle dba 8385 Aug 17 16:18 init.ora
-rw-r--r-- 1 oracle dba 12920 Aug 17 16:18 initdw.ora
-rw-r--r-- 1 oracle dba 1424 Aug 17 16:18 initora92.ora
-rw-r--r-- 1 oracle dba 25 Aug 17 16:18 initora921.ora
-rw-r--r-- 1 oracle dba 25 Aug 17 16:18 initora922.ora
-rw-r----- 1 oracle dba 1536 Aug 17 16:18 orapw
-rwSr----- 1 oracle dba 1536 Aug 17 16:18 orapwora921
-rw-r----- 1 oracle dba 1536 Aug 17 16:18 orapwora922
兩個(gè)數(shù)據(jù)庫(kù)實(shí)例的pfile文件內(nèi)容如下:
[icdnode1]$cat initora921.ora
SPFILE='/dev/rlv_spfile'
[icdnode1]$cat initora922.ora
SPFILE='/dev/rlv_spfile'
但initora92.ora文件是正常的有參數(shù)配置項(xiàng)目的文本文件,長(zhǎng)度比較大,再次不列出內(nèi)容。
雖然在dbs目錄下并沒(méi)有spfile文件,數(shù)據(jù)使用pfile啟動(dòng),但pfile又制定了spfile文件的位置,數(shù)據(jù)庫(kù)使用spfile文件啟動(dòng)。
上述的兩個(gè)實(shí)例的pfile文件是無(wú)法修改的,需要將pfile文件修改為常規(guī)的文本文件配置項(xiàng)才能進(jìn)行配置修改操作。
備份操作:
cd $ORACLE_HOME
cp –r dbs dbs_bak
2.3.2 修改數(shù)據(jù)庫(kù)參數(shù)文件
修改數(shù)據(jù)庫(kù)參數(shù)文件目的是修改配置項(xiàng)*.cluster_database=true → false,因此需要對(duì)pfile進(jìn)行操作,可以用如下方法還原pfile文件。
正常啟動(dòng)RAC數(shù)據(jù)庫(kù)的一個(gè)節(jié)點(diǎn),另一個(gè)節(jié)點(diǎn)關(guān)機(jī)或停止cluster進(jìn)程;
連接啟動(dòng)的實(shí)例并使用spfile配置生成pfile:
Sqlplus ‘/as sysdba’
SQL>create pfile from spfile;
SQL>exit
此時(shí)ORACLE_HOME目錄的dbs目錄中文件列表如下:
-rw-r--r-- 1 oracle dba 8385 Aug 17 16:15 init.ora
-rw-r--r-- 1 oracle dba 12920 Aug 17 16:15 initdw.ora
-rw-r--r-- 1 oracle dba 1425 Aug 17 16:29 initora92.ora
-rw-r--r-- 1 oracle dba 1425 Aug 17 16:32 initora921.ora
-rw-r--r-- 1 oracle dba 25 Aug 17 16:15 initora922.ora.bak
-rw-r----- 1 oracle dba 1536 Aug 17 16:15 orapw
-rwSr----- 1 oracle dba 1536 Aug 17 16:15 orapwora921
-rw-r----- 1 oracle dba 1536 Aug 17 16:15 orapwora922
可以看到initora921.ora文件長(zhǎng)度由原來(lái)的25字節(jié)變成1425,與initora92.ora文件長(zhǎng)度一致,也變成可編輯的文本文件。
initora92.ora和initora921.ora配置文件前幾行是一致的,將true修改為false
*.aq_tm_processes=0
*.background_dump_dest='/home/oracle/app/oracle/admin/ora92/bdump'
*.cluster_database_instances=2
*.cluster_database=true
ora921.cluster_interconnects='192.168.1.1'
ora922.cluster_interconnects='192.168.1.2'
pfile文件修改完成后關(guān)閉此節(jié)點(diǎn)的cluster服務(wù),數(shù)據(jù)庫(kù)也隨cluster關(guān)閉而關(guān)閉。
2.3.3 按非RAC模式操作指導(dǎo)修改字符集
將數(shù)據(jù)修改為非RAC模式后可按非RAC模式的操作指導(dǎo)進(jìn)行修改操作,操作時(shí)需要手工激活oracle系統(tǒng)vg。
2.3.4 修改完成后備份恢復(fù)
在非RAC模式完成字符集修改完成后,關(guān)閉數(shù)據(jù)庫(kù)將原dbs目錄恢復(fù),重新啟動(dòng)cluster軟件,在兩臺(tái)機(jī)器兩個(gè)實(shí)例查詢(xún)oracle服務(wù)器端字符集已經(jīng)成功修改。
2.4 RAC環(huán)境修改字符集快速步驟
總結(jié)上述操作步驟即操作過(guò)程,從理論上可以用以下步驟完成快速修改:
2.4.1 先修改spfile的參數(shù)
停止一個(gè)節(jié)點(diǎn)的cluster程序,在另一個(gè)節(jié)點(diǎn)執(zhí)行
Sqlplus ‘/as sysdba’
SQL> Alter system set cluster_database=false scope=spfile;
SQL>exit
2.4.2 進(jìn)行字符集修改
停止主節(jié)點(diǎn)的cluster程序,然后varyonvg oravg
然后用修改單機(jī)的操作步驟進(jìn)行字符集修改。
2.4.3 恢復(fù)spfile配置和RAC模式
Sqlplus ‘/as sysdba’
SQL> Alter system set cluster_database=true scope=spfile;
SQL>shutdown immediate
SQL>exit
啟動(dòng)兩個(gè)節(jié)點(diǎn)的cluster進(jìn)程,進(jìn)行驗(yàn)證測(cè)試