Welcome 微信登录

首页 / 数据库 / MySQL / Oracle 11.2.0.1关于NLS_LENGTH_SEMANTICS的一个Bug

这段时间在做数据迁移,需要从10g的ZHS16GBK字符集的数据库里面迁移数据到11g的UTF8字符的数据库,并且源数据库的NLS_LENGTH_SEMANTICS参数值为Byte,目标端的NLS_LENGTH_SEMANTICS参数值为CHAR。如果直接从源使用exp/expdp导出数据,然后使用imp/impdp导入数据到目标的话,可能会出现数据超长的情况,这时候就不好搞了,因此我就使用了中转的方式。即,把源数据导入到NLS_LENGTH_SEMANTICS参数值为CHAR的ZHS16GBK字符集的中转数据库中,然后再从中转数据库中导出数据并导入到目标数据库中。:这样做是有条件的,源数据库中没有长度超过4000/3个中文字符的CHAR/VARCHAR2字段,原因看这里继续这个问题,之所以这么做,目的是为了在数据部超长的情况得到CHAR/VARCHAR2类型字段以CHAR存储的数据。根据Oracle的定义,NLS_LENGTH_SEMANTICS参数可以在三个层次生效:数据库级、实例级、会话级,并且生效的优先顺序为会话级>实例级>数据库级。但是,我发现了一个问题:不管把NLS_LENGTH_SEMANTICS在那个级别设置为CHAR,在Oracle 11.2.0.1中,新导入表都不会使用CHAR做为CHAR/VARCHAR2等数据类型的存储单位,而是一律使用默认的Byte,除非源数据就已经指定了CHAR。请看如下实验过程,全过程均使用普通用户,因为NLS_LENGTH_SEMANTICS参数对sys用户无效:

先查看NLS_LENGTH_SEMANTICS参数,Database、Instance和Session都设置为CHAR
srcbdb@SYS> select * from nls_session_parameters where PARAMETER="NLS_LENGTH_SEMANTICS";

PARAMETER                      VALUE
------------------------------ --------------------------------------------------
NLS_LENGTH_SEMANTICS           CHAR
srcbdb@SYS> select * from nls_instance_parameters where PARAMETER="NLS_LENGTH_SEMANTICS";

PARAMETER                      VALUE
------------------------------ --------------------------------------------------
NLS_LENGTH_SEMANTICS           CHAR
srcbdb@SYS> select * from nls_database_parameters where PARAMETER="NLS_LENGTH_SEMANTICS";

PARAMETER                      VALUE
------------------------------ --------------------------------------------------
NLS_LENGTH_SEMANTICS           CHAR

然后倒入数据

[oracle@instsvr1 dumpdp]$ impdp vip/vip directory=dumpdir dumpfile=vip.byte.dat logfile=$ORACLE_SID.vip.impdp.`date +"%Y%m%d%H%M%S"`.log

Import: Release 11.2.0.1.0 - Production on Wed Mar 7 16:21:03 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options
Master table "VIP"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "VIP"."SYS_IMPORT_FULL_01":  vip/******** directory=dumpdir dumpfile=vip.byte.dat logfile=srcbdb.vip.impdp.20120307162103.log
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/DB_LINK
ORA-31685: Object type DB_LINK:"VIP"."DB_SRCBDATA" failed due to insufficient privileges. Failing sql is:
CREATE DATABASE LINK "DB_SRCBDATA"  CONNECT TO "SRCBDATA" IDENTIFIED BY VALUES "053E86648883623A93807EAD3C7A2EA776FA8F916A941AFB2E"  USING "srcbfin"
 
Processing object type SCHEMA_EXPORT/SEQUENCE/SEQUENCE
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/GRANT/OWNER_GRANT/OBJECT_GRANT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/FUNCTION/FUNCTION
Processing object type SCHEMA_EXPORT/PROCEDURE/PROCEDURE
Processing object type SCHEMA_EXPORT/FUNCTION/ALTER_FUNCTION
Processing object type SCHEMA_EXPORT/PROCEDURE/ALTER_PROCEDURE
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Job "VIP"."SYS_IMPORT_FULL_01" completed with 1 error(s) at 16:24:48

查看表结构
[oracle@instsvr1 dumpdp]$ sqlplus vip/vip

SQL*Plus: Release 11.2.0.1.0 Production on Wed Mar 7 14:56:04 2012

Copyright (c) 1982, 2009, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options

srcbdb@VIP> select * from tab where rownum <10;

TNAME                                                        TABTYPE         CLUSTERID
------------------------------------------------------------ -------------- ----------
DISCARD_TBDSCLIENT                                           TABLE
IT_AJDK                                                      TABLE
IT_DSDK                                                      TABLE
IT_DSDQCK                                                    TABLE
IT_DSHQCK                                                    TABLE
IT_DSKH                                                      TABLE
SNAPTBEXCHANGERATE                                           TABLE
TBADVICELOG                                                  TABLE
TBADVICELOGSETMEAL                                           TABLE

9 rows selected.

srcbdb@VIP> desc SNAPTBEXCHANGERATE
 Name                                                                                                              Null?    Type
 ----------------------------------------------------------------------------------------------------------------- -------- ----------------------------------------------------------------------------
 MONEY_TYPE                                                                                                          VARCHAR2(3)                      <--------------   这说明表是以Byte存储VARCHAR2数据类型的。
 TO_RMB_RATE                                                                                                         NUMBER(15,7)
 TO_USD_RATE                                                                                                         NUMBER(15,7)

我们再新建一个表看一下,注意,不显示指定CHAR或者Byte,数据使用默认值!srcbdb@VIP> create table lzb (col1 char(10),col2 varchar2(10));

Table created.

srcbdb@VIP> desc lzb
 Name                                                                                                              Null?    Type
 ----------------------------------------------------------------------------------------------------------------- -------- ----------------------------------------------------------------------------
 COL1                                                                                                                CHAR(10 CHAR)                   <--------------   这时候发现已经自动使用了CHAR。
 COL2                                                                                                                VARCHAR2(10 CHAR)
结论:在11.2.0.1里面,对于使用imp/impdp工具导入的数据,nls_length_semantics不生效!我不知道这是不是Oracle的Bug,看官也可以帮我求证一下!!!!

【附录:MOS上的文章】Examples and limits of BYTE and CHAR semantics usage (NLS_LENGTH_SEMANTICS) [ID 144808.1]Oracle 11gR201创建数据库时遭遇ORA-19202和ORA-31154的错误ORA-01659: 无法分配超出 7 的 MINEXTENTS (在表空间 DATA 中)相关资讯      Oracle基础 
  • Oracle基础介绍及常用相关SQL*PLUS  (03月11日)
  • Oracle 角色的两个特性和误区  (09/04/2012 05:56:16)
  • Oracle rac11.2.0.3.0的vip在重启  (09/02/2012 10:00:39)
  • Oracle中删除用户遇到的问题  (09/08/2012 20:01:42)
  • IMP-00008: unrecognized   (09/02/2012 10:03:25)
  • 在Oracle数据库上设置限制ip地址访  (09/02/2012 09:59:55)
本文评论 查看全部评论 (0)
表情: 姓名: 字数