字符集問題的初步探討(七)----關于字符集更改的內部操作
2024-07-21 02:06:49
供稿:網友
原文鏈接:
http://www.eygle.com/special/nls_character_set_07.htm
前面我們提到,通過修改props$的方式更改字符集在oracle7之后是一種極其危險的方式,應該盡量避免。
我們又知道,通過alter database character set更改字符集雖然安全可靠,但是有嚴格的子集和超集的約束,實際上我們很少能夠
用到這種方法。
實際上oracle還存在另外一種更改字符集的方式.
如果你注意過的話,在oracle的alert<sid>.log文件中,你可能看到過這樣的日志信息:
alter database character set internal_convert zhs16gbkupdating character set in controlfile to zhs16gbk sys.snap$ (rel_query) - clob representation altered sys.metastylesheet (stylesheet) - clob representation altered sys.external_tab$ (param_clob) - clob representation altered xdb.xdb$resource (sys_nc00027$) - clob representation altered odm.odm_pmml_dtd (dtd) - clob representation altered oe.warehouses (sys_nc00003$) - clob representation altered pm.online_media (sys_nc00042$) - clob representation altered pm.online_media (sys_nc00062$) - clob representation altered pm.online_media (product_text) - clob representation altered pm.online_media (sys_nc00080$) - clob representation altered pm.print_media (ad_sourcetext) - clob representation altered pm.print_media (ad_finaltext) - clob representation alteredcompleted: alter database character set internal_convert zhs1
在這里面,我們看到這樣一條重要的,oracle非公開的命令:
alter database character set internal_convert/ internal_use zhs16gbk
這個命令是當你選擇了使用典型方式創建了種子數據庫以后,oracle會根據你選擇的字符集設置,把當前種子數據庫的字符集更改為期望字符
集,這就是這條命令的作用.
在使用這個命令時,oracle會跳過所有子集及超集的檢查,在任意字符集之間進行強制轉換,所以,使用這個命令時你必須十分小心,你必須
清楚這一操作會帶來的風險.
我們之前講過的內容仍然有效,你可以使用csscan掃描整個數據庫,如果在轉換的字符集之間確認沒有嚴重的數據損壞,或者你可以使用有效
的方式更改,你就可以使用這種方式進行轉換.
我們來看一下具體的操作過程及oracle的內部操作:
這是alert.log文件中的記錄信息:
tue oct 19 16:26:30 2004
database characterset is zhs16gbk
replication_dependency_tracking turned off (no async multimaster replication found)
completed: alter database open
tue oct 19 16:27:07 2004
alter database character set internal_use zhs16cgb231280
updating character set in controlfile to zhs16cgb231280
tue oct 19 16:27:15 2004
thread 1 advanced to log sequence 118
current log# 2 seq# 118 mem# 0: /opt/oracle/oradata/primary/redo02.log
tue oct 19 16:27:15 2004
arc0: evaluating archive log 3 thread 1 sequence 117
arc0: beginning to archive log 3 thread 1 sequence 117
creating archive destination log_archive_dest_1: '/opt/oracle/oradata/primary/archive/1_117.dbf'
arc0: completed archiving log 3 thread 1 sequence 117
tue oct 19 16:27:20 2004
completed: alter database character set internal_use zhs16cgb231280
shutting down instance: further logons disabled
shutting down instance (immediate)
license high water mark = 1
tue oct 19 16:29:06 2004
alter database close normal
...
...
格式化10046跟蹤文件,得到以下信息(摘要):
alter session set events '10046 trace name context forever,level 12'alter database character set internal_use zhs16cgb231280call count cpu elapsed disk query current rows------- ------ -------- ---------- ---------- ---------- ---------- ----------parse 1 0.00 0.00 0 0 0 0execute 1 4.88 6.04 910 16825 18099 0fetch 0 0.00 0.00 0 0 0 0------- ------ -------- ---------- ---------- ---------- ---------- ----------total 2 4.88 6.04 910 16825 18099 0misses in library cache during parse: 1optimizer goal: chooseparsing user id: syselapsed times include waiting on following events: event waited on times max. wait total waited ---------------------------------------- waited ---------- ------------ control file sequential read 4 0.00 0.00 control file parallel write 2 0.05 0.08 log file sync 2 0.08 0.08 sql*net message to client 1 0.00 0.00 sql*net message from client 1 18.06 18.06********************************************************************************....update col$ set charsetid = :1 where charsetform = :2....update argument$ set charsetid = :1 where charsetform = :2....update collection$ set charsetid = :1 where charsetform = :2....update attribute$ set charsetid = :1 where charsetform = :2....update parameter$ set charsetid = :1 where charsetform = :2....update result$ set charsetid = :1 where charsetform = :2....update partcol$ set spare1 = :1 where charsetform = :2....update subpartcol$ set spare1 = :1 where charsetform = :2....update props$ set value$ = :1 where name = :2....update "sys"."kotad$" set sys_nc_rowinfo$ = :1 where sys_nc_oid$ = :2....update seq$ set increment$=:2,minvalue=:3,maxvalue=:4,cycle#=:5,order$=:6, cache=:7,highwater=:8,audit$=:9,flags=:10 where obj#=:1....update kopm$ set metadata = :1, length = :2 where name='db_fdo'....alter database close normal
此處生成的日志你可以在這里下載(供參考):
http://www.eygle.com/special/primary_ora_13730.zip
http://www.eygle.com/special/primary_ora_13730.tkf.log
我們看到這個過程和之前alter database character set操作的內部過程是完全相同的,也就是說internal_use提供的幫助就是使
oracle數據庫繞過了子集與超集的校驗.
這一方法在某些方面是有用處的,比如測試;應用于產品環境大家應該格外小心,除了你以外,沒有人會為此帶來的后果負責:
結語(我們不妨再說一次):
對于dba來說,有一個很重要的原則就是:不要把你的數據庫置于危險的境地!
這就要求我們,在進行任何可能對數據庫結構發生改變的操作之前,先做有效的備份,很多dba沒有備份的操作中得到了慘痛的教訓。
本文作者:
eygle,oracle技術關注者,來自中國最大的oracle技術論壇itpub.
www.eygle.com是作者的個人站點.你可通過[email protected]來聯系作者.歡迎技術探討交流以及鏈接交換.
原文出處:
http://www.eygle.com/special/nls_character_set_07.htm