Oracle 11g扩展统计信息(extension statistics)导致迁移19c报ORA-39083&&ORA-00904

Oracle 11g扩展统计信息(extension statistics)导致迁移19c报ORA-39083&&ORA-00904

前言

遇到个很有意思的问题。

11g迁移19c的过程,在19c impdp的时候遇到如下报错。

一开始怀疑是虚拟列的问题,于是11g查询dba_tab_cols视图,有如下:

select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN,HIDDEN_COLUMN from dba_tab_cols where owner='' and table_name='';

而在19c导入报错后,同样查询: 

select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN from dba_tab_cols where owner='' and table_name='';

19c的查询结果里边没有类似于SYS_STUJ3KC#SWJO6OK6YG7EPBX9YG那一大长串的列。

SYS_NC0004X$很好理解,这个是可能创建函数索引之后的辅助虚拟列,这个表是有一个函数索引的。

由于这类信息都由系统自动命名,名字不同很正常。

参考:Oracle中的SYS_NC00$ SYS_C000$ SYS_STU SYS_STS 和虚拟字段。

于是,在19c的impdp加上sqlfile查看实际上在数据库中跑的sql。在生成的sqlfile文件的最后,有一段sql如下:

-- fixup virtual columns... 
-- CONNECT SYS
ALTER TABLE "XXXXXX"."XXXXXX"  MODIFY ("SYS_STUJ3KC#SWJO6OK6YG7EPBX9YG" NUMBER GENERATED ALWAYS AS (SYS_OP_COMBINED_HASH("XXX_NO","XXX_DATE")) VIRTUAL );
-- done fixup virtual columns 

怀疑这个是19c impdp版本的新特性,于是在11g端同样使用sqlfile生成文件,则没有看到类似的fixup virtual columns。

确定这个是19c的新特性,当然也可能是12c以后的。

但是网上和mos都搜索不到啥,自己研究了下把报错模拟出来了。

结论

首先,先说为什么。

这个是由于11g中使用了拓展统计信息导致的。

简单百度个定义放在这里参考

我们在收集列的统计信息与直方图时,往往都是对某一列的收集。当谓词使用多个相关列时,会导致约束条件的冗余。这几个相关的列也被称作关联列。出现这种情况时,查询优化器也会做出不准确的判断。所以我们必须对这些相关列收集统计信息或直方图来描述这种依赖关系。

幸运的是,从Oracle 11g开始,数据库可以收集基于表达式或者一组列上的对象统计信息和直方图,从而解决这种问题。这种新的统计叫做扩展的统计信息(extension statistics)。

这种技术实际上是基于表达式或一组列创建一个隐藏列,叫做扩展(extension),再在扩展列上收集统计信息与直方图。

过程模拟

11g创建测试用户和测试表。

create user zkm identified by oracle;
grant dba to zkm;
CREATE TABLE zkm.test
(
  c1     NUMBER(6),
  c2       NUMBER(8,2),
  c3      NUMBER(8,2)
);
select dbms_metadata.get_ddl('TABLE','TEST','ZKM') from dual;
create index zkm.test on zkm.test(NVL(c3,0));
col column_name for a50
col DATA_DEFAULT for a50
set line 500
select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN,HIDDEN_COLUMN from dba_tab_cols where owner='ZKM' and table_name='TEST';
View Code
09:46:38 SYS@testdb(1155)> create user zkm identified by oracle;

User created.

Elapsed: 00:00:00.03
09:46:47 SYS@testdb(1155)> grant dba to zkm;

Grant succeeded.

Elapsed: 00:00:00.01
09:46:51 SYS@testdb(1155)> CREATE TABLE zkm.test
09:47:01   2  (
09:47:06   3    c1     NUMBER(6),
09:47:06   4    c2       NUMBER(8,2),
09:47:06   5    c3      NUMBER(8,2)
09:47:06   6  );

Table created.

Elapsed: 00:00:00.01
09:50:19 SYS@testdb(1155)> desc zkm.test
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 C1                                                 NUMBER(6)
 C2                                                 NUMBER(8,2)
 C3                                                 NUMBER(8,2)

09:50:20 SYS@testdb(1155)> select dbms_metadata.get_ddl('TABLE','TEST','ZKM') from dual;

DBMS_METADATA.GET_DDL('TABLE','TEST','ZKM')
--------------------------------------------------------------------------------

  CREATE TABLE "ZKM"."TEST"
   (    "C1" NUMBER(6,0),
        "C2" NUMBER(8,2),
        "C3" NUMBER(8,2)
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENT
S 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_F
LASH_CACHE DEFAULT)
  TABLESPACE "USERS"



Elapsed: 00:00:00.24

09:52:01 SYS@testdb(1155)> create index zkm.test on zkm.test(NVL(c3,0));

Index created.

Elapsed: 00:00:00.01

09:52:48 SYS@testdb(1155)> col column_name for a50
09:53:01 SYS@testdb(1155)> col DATA_DEFAULT for a50
09:53:08 SYS@testdb(1155)> set line 500
09:53:13 SYS@testdb(1155)> select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN,HIDDEN_COLUMN from dba_tab_cols where owner='ZKM' and table_name='TEST';

COLUMN_NAME                                        DATA_DEFAULT                                       VIRTUAL_C HIDDEN_CO
-------------------------------------------------- -------------------------------------------------- --------- ---------
C1                                                                                                    NO        NO
C2                                                                                                    NO        NO
C3                                                                                                    NO        NO
SYS_NC00004$                                       NVL("C3",0)                                        YES       YES

Elapsed: 00:00:00.01

  

接下来创建扩展统计信息(extension statistics)。

09:55:41 SYS@testdb(1155)> SELECT DBMS_STATS.CREATE_EXTENDED_STATS(OWNNAME  => 'ZKM',TABNAME  => 'TEST',EXTENSION => '(c1,c2)') FROM DUAL;

DBMS_STATS.CREATE_EXTENDED_STATS(OWNNAME=>'ZKM',TABNAME=>'TEST',EXTENSION=>'(C1,C2)')
----------------------------------------------------------------------------------------
SYS_STUF3GLKIOP5F4B0BTTCFTMX0W

Elapsed: 00:00:00.22
09:55:42 SYS@testdb(1155)> select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN,HIDDEN_COLUMN from dba_tab_cols where owner='ZKM' and table_name='TEST';

COLUMN_NAME                                        DATA_DEFAULT                                       VIRTUAL_C HIDDEN_CO
-------------------------------------------------- -------------------------------------------------- --------- ---------
C1                                                                                                    NO        NO
C2                                                                                                    NO        NO
C3                                                                                                    NO        NO
SYS_NC00004$                                       NVL("C3",0)                                        YES       YES
SYS_STUF3GLKIOP5F4B0BTTCFTMX0W                     SYS_OP_COMBINED_HASH("C1","C2")                    YES       YES

Elapsed: 00:00:00.00

在11g将用户zkm导出(过程略)。

create directory dir20210712 as '/home/oracle/daily/20210712';
expdp ' / as sysdba ' directory=dir20210712 dumpfile=zkm.dmp logfile=zkm.log cluster=n schemas=zkm

将文件zkm.dmp传至19c环境上。

创建directory后执行导入操作成功将报错模拟出来:

[oracle@testdb 20210712]$ impdp ' / as sysdba ' directory=dir20210712 dumpfile=zkm.dmp logfile=zkm.log cluster=n

Import: Release 19.0.0.0.0 - Production on Mon Jul 12 10:17:29 2021
Version 19.11.0.0.0

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

Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Master table "SYS"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "SYS"."SYS_IMPORT_FULL_01":  "/******** AS SYSDBA" directory=dir20210712 dumpfile=zkm.dmp logfile=zkm.log cluster=n 
Processing object type SCHEMA_EXPORT/USER
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/ROLE_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "ZKM"."TEST"                                    0 KB       0 rows
ORA-39083: Object type TABLE:"ZKM"."TEST" failed to create with error:
ORA-00904: "SYS_STUF3GLKIOP5F4B0BTTCFTMX0W": invalid identifier

Failing sql is:
ALTER TABLE "ZKM"."TEST"  MODIFY ("SYS_STUF3GLKIOP5F4B0BTTCFTMX0W" NUMBER GENERATED ALWAYS AS (SYS_OP_COMBINED_HASH("C1","C2")) VIRTUAL )

Processing object type SCHEMA_EXPORT/TABLE/INDEX/FUNCTIONAL_INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/FUNCTIONAL_INDEX/INDEX_STATISTICS
Job "SYS"."SYS_IMPORT_FULL_01" completed with 1 error(s) at Mon Jul 12 10:17:41 2021 elapsed 0 00:00:12

使用sqlfile有如下信息:

-- fixup virtual columns... 
ALTER TABLE "ZKM"."TEST"  MODIFY ("SYS_STUF3GLKIOP5F4B0BTTCFTMX0W" NUMBER GENERATED ALWAYS AS (SYS_OP_COMBINED_HASH("C1","C2")) VIRTUAL );
-- done fixup virtual columns 

19c查看dba_tab_cols,有:

col column_name for a50
col DATA_DEFAULT for a50
set line 500
select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN,HIDDEN_COLUMN from dba_tab_cols where owner='ZKM' and table_name='TEST';
View Code
10:22:32 SYS@19ctestdb(30)> set line 500
10:22:38 SYS@19ctestdb(30)> col column_name for a50
10:23:00 SYS@19ctestdb(30)> col DATA_DEFAULT for a50
10:23:00 SYS@19ctestdb(30)> set line 500
10:23:00 SYS@19ctestdb(30)> select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN,HIDDEN_COLUMN from dba_tab_cols where owner='ZKM' and table_name='TEST';

COLUMN_NAME                                        DATA_DEFAULT                                       VIRTUAL_C HIDDEN_CO
-------------------------------------------------- -------------------------------------------------- --------- ---------
C1                                                                                                    NO        NO
C2                                                                                                    NO        NO
C3                                                                                                    NO        NO
SYS_NC00004$                                       NVL("C3",0)                                        YES       YES

Elapsed: 00:00:00.01

解决方法

11g迁移19c遇到这个问题,由于原因是扩展统计信息(extension statistics)引起的,因此忽略该报错。

手工在19c上创建拓展统计信息:

10:26:39 SYS@19ctestdb(30)> SELECT DBMS_STATS.CREATE_EXTENDED_STATS(OWNNAME  => 'ZKM',TABNAME  => 'TEST',EXTENSION => '(c1,c2)') FROM DUAL;

DBMS_STATS.CREATE_EXTENDED_STATS(OWNNAME=>'ZKM',TABNAME=>'TEST',EXTENSION=>'(C1,C2)')
------------------------------------------------------------------------------------------
SYS_STUF3GLKIOP5F4B0BTTCFTMX0W

Elapsed: 00:00:00.05
10:27:26 SYS@19ctestdb(30)> select COLUMN_NAME,DATA_DEFAULT,VIRTUAL_COLUMN,HIDDEN_COLUMN from dba_tab_cols where owner='ZKM' and table_name='TEST';

COLUMN_NAME                                        DATA_DEFAULT                                       VIRTUAL_C HIDDEN_CO
-------------------------------------------------- -------------------------------------------------- --------- ---------
SYS_STUF3GLKIOP5F4B0BTTCFTMX0W                     SYS_OP_COMBINED_HASH("C1","C2")                    YES       YES
C1                                                                                                    NO        NO
C2                                                                                                    NO        NO
C3                                                                                                    NO        NO
SYS_NC00004$                                       NVL("C3",0)                                        YES       YES

Elapsed: 00:00:00.00

或者,等官方出正式解决方法比如补丁或者该参数啥的其他方式。

至此。

原文地址:https://www.cnblogs.com/PiscesCanon/p/15000765.html