expdp时报错ORA-31693&ORA-02354&ORA-01555

问题描述

expdp进行导出时提示如下报错:

[root@topecps backup]# sjtbk/sjtbk@sjtbk directory=oracle dumpfile=sjtbk.dmp logfile=sjtbk.log
....
ORA-31693: 表数据对象 "SJTBK"."INC_KETTLE_ETL_HIST" 无法加载/卸载并且被跳过, 错误如下:
ORA-02354: 导出/导入数据时出错
ORA-01555: 快照过旧: 回退段号 57 (名称为 "_SYSSMU57_3964901489$") 过小
. . 导出了 "SJTBK"."WS2_WSSL"                          105.3 GB 3991552 行
ORA-31693: 表数据对象 "SJTBK"."ECPS_EASY_LOGOUT" 无法加载/卸载并且被跳过, 错误如下:
ORA-02354: 导出/导入数据时出错
ORA-01555: 快照过旧: 回退段号 22 (名称为 "_SYSSMU22_2857247234$") 过小

问题原因

业务未停止或未停止完全;

回滚段设置太小;

在执行导出或查询某张表的时候,又有其它用户对该表进行了行修改;
修改提交后,通常UNDO中会保留这些旧的资料,用来保证数据一致性读。如果UNDO保留时间到了,并且UNDO中无足够空间,这些在UNDO中的旧资料就会被覆盖。那些依靠这些数据的操作就无法获得一致性读,从而报错:ORA-01555。
建议修改undo_retention到合适的大小或者对undo tablespace size扩容

--查看回滚段参数  单位秒
SQL> show parameter undo_retention

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
undo_retention			     integer	 900

解决办法

停止监听

发现现场监听未停止,避免业务连进来将监听停止。

[oracle@topecps ~]$ lsnrctl stop

LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 12-1月 -2024 18:06:41

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

正在连接到 (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=topecps)(PORT=1521)))
命令执行成功
[oracle@topecps ~]$ lsnrctl status

LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 12-1月 -2024 18:06:56

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

正在连接到 (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=topecps)(PORT=1521)))
TNS-12541: TNS: 无监听程序
 TNS-12560: TNS: 协议适配器错误
  TNS-00511: 无监听程序
   Linux Error: 111: Connection refused

查看undo表空间利用率

检查是否利用率过高,可以适当添加表空间数据文件

--查看undo表空间利用率
select a.*
    , cast(a.used_gb*100.0 / a.max_gb as number(18,1)) as used_percent
from (
select tablespace_name
    , cast(sum(bytes)/1024/1024/1024 as number(18,1)) as used_gb 
    , cast(sum(maxbytes)/1024/1024/1024 as number(18,1)) as max_gb 
from dba_data_files 
where tablespace_name like '%UNDO%' 
group by tablespace_name
) a;

TABLESPACE_NAME 		  USED_GB     MAX_GB USED_PERCENT
------------------------------ ---------- ---------- ------------
UNDOTBS1			     47.2	  32	    147.5

--查看undo表空间
SQL> col file_name for a50
SQL> set linesize 999
SQL> select tablespace_name,file_name,AUTOEXTENSIBLE,INCREMENT_BY,ONLINE_STATUS,STATUS,MAXBYTES from dba_data_files where tablespace_name='UNDOTBS1';

TABLESPACE_NAME 	       FILE_NAME					  AUT INCREMENT_BY ONLINE_ STATUS      MAXBYTES
------------------------------ -------------------------------------------------- --- ------------ ------- --------- ----------
UNDOTBS1		       /opt/u01/app/oracle/oradata/sjtbk/undotbs01.dbf	  YES	       640 ONLINE  AVAILABLE 3.4360E+10
UNDOTBS1		       /opt/u01/app/oracle/oradata/sjtbk/undotbs03.dbf	  NO		 0 ONLINE  AVAILABLE	      0

--增加undo表空间
alter tablespace undotbs1 add datafile '/opt/u01/app/oracle/oradata/sjtbk/undotbs04.dbf' size 1G  autoextend on next 128M maxsize UNLIMITED;

查看系统参数,适当调大 retention

--查看回滚段参数  单位秒
SQL> show parameter undo_retention

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
undo_retention			     integer	 900

--适当调大 retention
SQL> alter system set undo_retention=86400 scope=both;

系统已更改。

SQL> exit

排查是否有LOB字段的行存在损坏(可选)

创建表存放lob损坏行的rowid

--创建表存放lob损坏行的rowid
create table corrupted_lob_data (corrupt_rowid rowid, err_num number);

找出存在损坏lob的行

declare
error_1578 exception;
error_1555 exception;
error_22922 exception;
pragma exception_init(error_1578,-1578);
pragma exception_init(error_1555,-1555);
pragma exception_init(error_22922,-22922);
n number;
begin
  for cursor_lob in (select rowid r, &&lob_column from &table_owner..&table_with_lob) loop
    begin
      n := dbms_lob.instr (cursor_lob.&&lob_column, hextoraw ('889911')) ;
exception
when error_1578 then
insert into corrupted_lob_data values (cursor_lob.r, 1578);
commit;
when error_1555 then
insert into corrupted_lob_data values (cursor_lob.r, 1555);
commit;
when error_22922 then
insert into corrupted_lob_data values (cursor_lob.r, 22922);
commit;
end;
end loop;
end;
/

Enter value for lob_column: BYTE_IMAGE
Enter value for table_owner: USER1
Enter value for table_with_lob: TKINFO
old 10: for cursor_lob in (select rowid r, &&lob_column from &table_owner..&table_with_lob) loop
new 10: for cursor_lob in (select rowid r, BYTE_IMAGE from USER1.TKINFO) loop
old 12: num := dbms_lob.instr (cursor_lob.&&lob_column, hextoraw ('889911')) ;
new 12: num := dbms_lob.instr (cursor_lob.BYTE_IMAGE, hextoraw ('889911')) ;

发现rowid为AAAhS4AAUAAE3IRAAC的行 blob列有损坏

SQL> select * from corrupted_lob_data;
CORRUPT_ROWID ERR_NUM
------------------ ----------
AAAhS4AAUAAE3IRAAC 1555

修改导出语句,跳过blob损坏的行,重新导出,成功导出

expdp user1/XXXXXXXX directory=szdata1 dumpfile=szhzinfo_20180319.dmp logfile=szhzinfo_20180319.log exclude=STATISTICS,INDEX tables=TKINFO QUERY=\"WHERE rowid NOT IN \(\'AAAhS4AAUAAE3IRAAC\'\) and voteproccesstime between 20180304000000 and 20180304235959 \"

修改含lob字段表中字段的 retention(可选)

如果表中含有lob字段,修改 undo_retention 后,需要单独修改表字段的 retention

--查含lob字段的表
select * from dba_lobs
WHERE OWNER = USER
AND TABLE_NAME LIKE '%DOC'
ORDER BY TABLE_NAME;

--更改含lob字段表中字段的 retention
ALTER TABLE EHR_HEALTHRECORD_DOC MODIFY LOB(DOCCONTENT)(retention);

批量调整表的保留时间(可选)

select 'ALTER TABLE '|| table_name ||' MODIFY LOB('|| column_name ||')(retention);'
from dba_lobs
WHERE OWNER = USER
AND TABLE_NAME LIKE '%DOC'
ORDER BY TABLE_NAME;

执行以上拼接结果的sql

再次导出未报错。

参考链接:expdp错误,ORA-01555: 快照过旧_expdp ora-01555-CSDN博客

你可能感兴趣的:(expdp时报错)