今天使用exp转数据库报错ora-01555,在网上搜索发现一篇比较好的文章,特转来分享学习!
[@more@]数据库环境:两台DB都是oracle9.2.0.4
导入工具使用:powercenter8.6
主库是redhat linux4.7
备库是windows2003(32位)环境
在导入过程中,报:
ORA-01555: 快照过旧: 回退段号 1 在名称为 "_SYSSMU1$" 过小
错误。
1555错误产生的原因,就需要知道Oracle的两个特性:一致性读(Consistent Get)和延迟块清除(Delayed Block Cleanout)。此外,还要知道关于回滚段的一些配置参数:
相关参数
先看下Oracle中关于UNDO有哪些配置参数:
SQL> show parameter undo
NAME TYPEVALUE
--------------------- -------------------- -----------------------
undo_management
stringMANUAL
undo_retention
integer900
undo_suppress_errors
boolean
FALSE
undo_tablespace
stringUNDOTBS1
undo_management
回滚段的管理方式。值可以为MANUAL/AUTO。9i中默认是MANUAL,10G中默认是AUTO。
从9i后,回滚段就以表空间的形式管理,并且支持系统自动管理回滚段。一个回滚表空间上可以创建多个回滚段,一个数据库可以创建多个回滚表空间。但是,一个实例(Instance)只能使用一个回滚表空间。
如果undo_management设置为MANUAL,就是手动创建回滚段:
SQL> create rollback segment undo1tablespaceUNDOTBS1;
如果设置为AUTO,Oracle就自动管理回滚段的创建,而手工创建就会失败。
undo_retention
这个参数设置回滚段中的被提交或回滚的数据强制保留时间,单位是秒。请注意,这个参数和1555错误有非常大的关系。但是,需要提醒的是,并不是回滚段中的数据超过这个时间以后就会被清除掉,而是等到后面事务产生的回滚数据覆盖掉“超期”数据。所以这就是为什么我们往往看到系统的回滚表空间占有率始终是100%的原因了。
undo_suppress_errors
是否报与回滚段有关的错误。如果为FALSE,就不会产生与回滚段有关的错误。但是,请注意,并不是不会发生回滚段错误,而只是屏蔽错误信息,错误发生了就会存在滴。在10g中,这个参数是隐含参数。
undo_tablespace
为每个实例制定的唯一当前使用的回滚段表空间。
面我们就模拟一下1555错误发生的情况:
首先建立测试环境。由于我们只是要模拟1555错误的发生,所以需要建立一个小的回滚表空间,并且设置undo_retention时间为1(秒),以便回滚数据尽快被覆盖(呵呵,要防止1555错误发生,这就一定要避免的)。
CREATE UNDO TABLESPACErbs_ts
DATAFILE 'rbs_ts2.dbf' SIZE10MAUTOEXTEND OFF;
alter
system setundo_retention=1 scope=spfile;
alter
system setundo_management=auto scope=spfile;
alter
system setundo_tablespace=rbs_tsscope=spfile;
startup
force
alter
tablespacerbs_tsonline;
create
tabledemo.t_dualas select * from dual;
insert
intot_dualvalues(1);
commit
;
一致性读导致的1555错误
开始读取表。
SQL>
SQL>varclrefcursor
SQL> begin
2open:clfor select * fromdemo.t_multiver;
3end;
4/
PL/SQL procedure successfully completed.
SQL>
更新表数据,产生回滚信息。
SQL> updatedemo.t_multiverset b = 111 where a = 1;
1 row updated.
SQL> commit;
Commit complete.
运行大批其他事务,充满所有回滚段,以致覆盖上面的回滚信息。回滚段可以通过dba_rollback_segs查看。
SQL> begin
2foriin 1..20000loop
3updatedemo.t_dualset dummy=1;
4commit;
5end loop;
6end;
7
8/
PL/SQL procedure successfully completed.
SQL> /
PL/SQL procedure successfully completed.
查询到更新过的数据记录,回滚信息已经被覆盖,所以报1555错误。
SQL>print :cl
ERROR:
ORA-01555: snapshot too old: rollback segment number 18 with name "_SYSSMU18$"
too
small
no
rows selected
SQL>
延迟块清除导致的1555错误
开始读取表。
SQL>varccrefcursor
SQL>
SQL> begin
2open:cc for select * fromt_multiver;
3end;
4/
这时一个事务更新了该数据块,但在提交前,我们手工将buffer cache中的数据做了flush,再做提交。这时的数据块上只记录了锁标志,没有事务标志和Commit SCN。
PL/SQL procedure successfully completed.
SQL>
SQL> updatet_multiverset b=115 where a=1;
1 row updated.
SQL>
SQL> alter system flushbuffer_cache;
System altered.
SQL>
SQL> commit;
Commit complete.
进行非常多的事务,将回滚段中的事务信息表中的数据全部覆盖:
SQL>
SQL> begin
2--overwriterollback slot
3foriin 1..40000loop
4 updatet_dualset dummy=1;
5commit;
6end loop;
7end;
8/
PL/SQL procedure successfully completed.
读取数据块前需要到回滚段的事务信息表中读取Itl中没有标记完全的事务的状态和Commit SCN,以判断是否需要进行一致性读。但是事务信息表中的数据都已经被覆盖,所以报1555错误:
SQL>
SQL>print :cc
ERROR:
ORA-01555: snapshot too old: rollback segment number 20 with name "_SYSSMU20$"
too
small
no
rows selected
以上两个例子看起来是好像很类似,但是,他们的本质区别是:第一个实际上是在进行一致性读得时候发生的1555错误,而第二个例子是在判断是否需要进行一致性读得时候发生的1555错误。
解决1555错误的方法
现在,我们已经知道了1555错误产生的原因。那么,就可以总结出以下方法来解决1555错误问题:
1、扩大回滚段
因为回滚段是循环使用的,如果回滚段足够大,那么那些被提交的数据信息就能保存足够长的时间是那些大事务完成一致性读取。
2、增加undo_retention时间
在undo_retention规定的时间内,任何其他事务都不能覆盖这些数据。
3、优化相关查询语句,减少一致性读。
减少查询语句的一致性读,就降低读取不到回滚段数据的风险。这一点非常重要!
4、减少不必要的事务提交
提交的事务越少,产生的回滚段信息就越少。
5、对大事务指定回滚段
通过以下语句可以指定事务的回滚段:
SET TRANSACTION USE ROLLBACK SEGMENTrollback_segment
;
给大事务指定回滚段,即降低大事务回滚信息覆盖其他事务的回滚信息的几率,又降低了他自身的回滚信息被覆盖的几率。大事务的存在,往往是1555错误产生的诱因。
6、使用游标时尽量使用显式游标,并且只在需要的时候打开游标,同时将所有可以在游标外做的操作从游标循环中拿出。
当游标打开时,查询就开始了,直到游标关闭。减少游标的打开时间,就减少了1555错误发生的几率。
在本次操作中,笔者的解决方案是:
1.适当增大undo表空间的尺寸,防止回滚信息被覆盖。
2.增加undo_retention时间,增加到10800秒(在导入源和导出源都修改)。
3.删除目标表的部分索引,加快导入速度,在倒完数据后,再建立。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23307206/viewspace-1037739/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/23307206/viewspace-1037739/