Oracle数据库 加入小组

59个成员 56个话题 创建时间:2021-01-15

【故障处理】19c PDB中创建外部表时,出现KUP-04040报错

发表于2021-03-07 6695次查看

【故障描述】

使用网络连接的方式登录19c的PDB,然后创建oracle_loader驱动模式的外部表。创建成功后,在检索数据时,出现KUP-04040的报错,过程如下:

[oracle@sdedu ~]$ sqlplus sys/oracle@pdb1 as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Sun Mar 7 18:12:34 2021
Version 19.3.0.0.0

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


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

SQL> create directory dmp_dir as '/home/oracle/ext_table/';

Directory created.

SQL> CREATE TABLE emp_load 
  2  (
  3   first_name CHAR(15), 
  4   last_name CHAR(20), 
  5   year_of_birth CHAR(4)
  6  )
  7  ORGANIZATION EXTERNAL 
  8  (
  9    TYPE ORACLE_LOADER 
 10    DEFAULT DIRECTORY dmp_dir
 11    ACCESS PARAMETERS 
 12    (
 13     RECORDS DELIMITED BY '|'
 14     DISABLE_DIRECTORY_LINK_CHECK
 15     FIELDS TERMINATED BY ','
 16    (
 17     first_name CHAR(7),
 18     last_name CHAR(8),
 19     year_of_birth CHAR(4))
 20    )
 21     LOCATION ('info.dat')
 22  )
 23  REJECT LIMIT UNLIMITED
 24  ;

Table created.

SQL> select * from emp_load;
select * from emp_load
*
ERROR at line 1:
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-04040: file info.dat in DMP_DIR not found

【解决过程】

经过测试发现,如果在session中切换容器到pdb1中,访问就是正常的。

SQL> alter session set container=pdb1;

Session altered.

SQL> select * from emp_load;

FIRST_NAME      LAST_NAME            YEAR
--------------- -------------------- ----
Alvin           Tolliver             1976
Kenneth         Baer                 1963
Mary            Dube                 1973

SQL> 

这个报错,和可能是由于文件和目录权限导致,因此检查一下权限:

[oracle@sdedu ~]$ ls -alt ext_table/
total 24
drwx------. 29 oracle oinstall 4096 Mar  7 21:10 ..
drwxrwxrwx   2 oracle oinstall  100 Mar  7 18:51 .
-rwxrwxrwx   1 oracle oinstall   55 Mar  7 17:59 INFO.DAT
[oracle@sdedu ~]$ 

从文件的权限没有问题,目录的权限也是没有问题。但为啥还是不行呢?

索性换一下目录来出来吧。

我们使用pdb1默认的DATA_PUMP_DIR目录来进行外部表的创建。

/u01/app/oracle/admin/SS19C/dpdump/ADB4AF11A2A07F0BE0530A0200C001E6

此时发现成功了!

[oracle@sdedu ADB4AF11A2A07F0BE0530A0200C001E6]$ sqlplus sys/oracle@pdb1 as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Sun Mar 7 21:31:24 2021
Version 19.3.0.0.0

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


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

SQL> drop table emp_load;

Table dropped.
 
SQL> CREATE TABLE emp_load
  2  (
  3   first_name CHAR(15),
  4   last_name CHAR(20), 
  5   year_of_birth CHAR(4)
  6  )
  7  ORGANIZATION EXTERNAL 
  8  (
  9    TYPE ORACLE_LOADER 
 10    DEFAULT DIRECTORY DATA_PUMP_DIR
 11    ACCESS PARAMETERS 
 12    (
 13     RECORDS DELIMITED BY '|'
 14     FIELDS TERMINATED BY ','
 15    (
 16     first_name CHAR(7),
 17     last_name CHAR(8),
 18     year_of_birth CHAR(4))
 19    )
 20     LOCATION ('INFO.DAT')
 21  )
 22  REJECT LIMIT UNLIMITED
 23  ;

Table created.

SQL> select * from emp_load;

FIRST_NAME      LAST_NAME            YEAR
--------------- -------------------- ----
Alvin           Tolliver             1976
Kenneth         Baer                 1963
Mary            Dube                 1973

SQL> 

换一个目录在测试一下,也是成功了,此时发现ORIGIN_CON_ID也为1,1代表根容器。看来要想成功,ORIGIN_CON_ID列必须为1,也就是从根容器继承过来的。

[oracle@sdedu ext_table]$ sqlplus sys/oracle@pdb1 as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Sun Mar 7 22:46:22 2021
Version 19.3.0.0.0

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


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

SQL> select * from dba_directories where directory_name='SDO_DIR_ADMIN';

  
OWNER    DIRECTORY_NAME   DIRECTORY_PATH                                   ORIGIN_CON_ID
-------- --------------- ------------------------------------------------- -------------
SYS      SDO_DIR_ADMIN   /u01/app/oracle/product/19.3.0/dbhome_1/md/admin   1


1 rows selected.


SQL> show pdbs;

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         3 PDB1                           READ WRITE NO

SQL> !cp /home/oracle/ext_table/INFO.DAT /u01/app/oracle/product/19.3.0/dbhome_1/md/admin/

SQL> drop table emp_load;

Table dropped.

SQL> CREATE TABLE emp_load
  2  (
  3   first_name CHAR(15),
  4   last_name CHAR(20), 
  5   year_of_birth CHAR(4)
  6  )
  7  ORGANIZATION EXTERNAL 
  8  (
  9    TYPE ORACLE_LOADER 
 10    DEFAULT DIRECTORY SDO_DIR_ADMIN
 11    ACCESS PARAMETERS 
 12    (
 13     RECORDS DELIMITED BY '|'
 14     FIELDS TERMINATED BY ','
 15    (
 16     first_name CHAR(7),
 17     last_name CHAR(8),
 18     year_of_birth CHAR(4))
 19    )
 20     LOCATION ('INFO.DAT')
 21  )
 22  REJECT LIMIT UNLIMITED
 23  ;

Table created.

SQL> select * from emp_load;

FIRST_NAME      LAST_NAME            YEAR
--------------- -------------------- ----
Alvin           Tolliver             1976
Kenneth         Baer                 1963
Mary            Dube                 1973

SQL> 

在创建Directory时,是无法指定ORIGIN_CON_ID来源的。在那个容器创建,就会是那个容器的ID。这种策略很可能是BUG。

最终,由于目录权限问题导致创建外部表失败,此时我们可以使用PDB默认的DUMP目录,也就是ORIGIN_CON_ID为1的目录,来避免这个错误。

【参考资料】

ORA-29913: Error in Executing ODCIEXTTABLEOPEN Callout (Doc ID 458620.1)

发表回复
你还没有登录,请先 登录或 注册!