今天早上在日志中发现exp备份时出错:
. . exporting table BJ_AFFILIATES 37 rows exported
EXP-00008: ORACLE error 904 encountered
ORA-00904: : invalid identifier
. . exporting table BJ_CATEGORIES 175 rows exported
EXP-00008: ORACLE error 1003 encountered
ORA-01003: no statement parsed
. . exporting table BJ_LOCATION 12 rows exported
EXP-00008: ORACLE error 904 encountered
ORA-00904: : invalid identifier
. . exporting table BJ_TYPE 22 rows exported
EXP-00008: ORACLE error 1003 encountered
ORA-01003: no statement parsed
此错误对前台应用没有任何影响。导出的用户是系统新版本上线时创建的一个新用户,操作过程很简单,从老用户中exp数据,然后imp到新用户,导入导出过程都很正常,没有任何报错,查看错误类型含义:
[oracle@bj47 backup]$ oerr ora 904
00904, 00000, "%s: invalid identifier"
// *Cause:
// *Action:
[oracle@bj47 backup]$ oerr ora 1003
01003, 00000, "no statement parsed"
// *Cause:
// *Action:
看来无法得到原因和采取的活动。网上查询,很多解释都是不同版本的客户端和服务器之间进行exp而导致的,而我的操作是在同一台机器上,显然不是原因。从表DBA_SERVER_ERROR表中查看相应sql,发现如下sql:
SELECT CNAME, SNAME, SSGFLAG, STSNAME, STSNO, SFILE, SBLOCK, SDOBJID, SCHUNKING, SVPOOL, SFLAGS, INAME, ISGFLAG, ITSNAME, ITSNO, IFILE, IBLOCK, IDOBJID, IINITRANS, IMAXTRANS, SPROPERTY, COLTYPE, COLTYPFLG, BLOCKSIZE, INTCOLID, OPAQUETYPE FROM SYS.EXU9LOBU
WHERE TOBJID = :1
用sql trace追踪也发现类似的错误,步骤如下:
1、alter system set events='904 trace name errorstack';
2、执行exp
3、在udump下的trace文件中发现:
*** SESSION ID:(44.28384) 2008-06-12 11:11:38.105
*** 2008-06-12 11:11:38.105
ksedmp: internal or fatal error
ORA-00904: : invalid identifier
Current SQL statement for this session:
SELECT BUCKET, ENDPTHASH, ENDPTVAL, UTL_RAW.CAST_TO_RAW(ENDPTVAL) ENDPTVAL_RAW FROM SYS.EXU8HSTU WHERE POBJ
ID = :1 AND INTCOL = :2 ORDER BY BUCKET
检查对象EXU8HSTU ,发现它的select权限已经赋予了public用户,也就是所有用户应该都可以访问的:
SQL> select * from dba_tab_privs where table_name='EXU8HSTU'
2 ;
GRANTEE OWNER TABLE_NAME GRANTOR PRIVILEGE GRANTABLE HIERARCHY
------------------------------ ------------------------------ ------------------------------ ------------------------------ ---------------------------------------- --------- ---------
PUBLIC SYS EXU8HSTU SYS SELECT NO NO
那么难道是新用户对UTL_RAW包没有可执行权限?
SQL> select * from dba_tab_privs where table_name='UTL_RAW';
果然,记录为空,也就是新用户并没有包UTL_RAW的可执行权限,找到原因就好比了,给新用户赋予包UTL_RAW的可执行权限即可:
grant execute on UTL_RAW to newuser;
SQL> select * from dba_tab_privs where table_name='UTL_RAW';
GRANTEE OWNER TABLE_NAME GRANTOR PRIVILEGE GRANTABLE HIERARCHY
------------------------------ ------------------------------ ------------------------------ ------------------------------ ---------------------------------------- --------- ---------
NEWUSER SYS UTL_RAW SYS EXECUTE NO NO
赋予成功后,exp备份也恢复正常。
仔细回想,UTL_RAW的可执行权限为何会被取消?原来是很久以 前404检查的时候要求将所有UTL开头的包的可执行权限从public用户中取消掉,那么老用户备份的时候怎么就没有报错呢?查询以前的备份日志,发现 其实也含有这样的错误,但是只是在某一个表上,因此没有引起注意:
About to export specified tables via Direct Path ...
. . exporting table BJ_AFFILIATES
37 rows exported
. . exporting table BJ_CATEGORIES
175 rows exported
. . exporting table BJ_LOCATION
12 rows exported
. . exporting table BJ_TYPE
22 rows exported
. . exporting table NG_ADDISTRIBUTIONS
.
117949 rows exported
. . exporting table NG_ADMANAGERDB_LOCK
1 rows exported
. . exporting table NG_ADS
.
118197 rows exported
. . exporting table NG_ADSIZES
144 rows exported
. . exporting table NG_ADTARGETS
1 rows exported
. . exporting table NG_ADVERTISERS
1775 rows exported
EXP-00008: ORACLE error 904 encountered
ORA-00904: : invalid identifier
. . exporting table NG_ADVERTISERTYPES
。。。。。。
只有为什么老用户只有一个表报错,而新用户所有表都报错,就不得而知了。。。。。。