导数据遇见ORA-01555错误

昨天在对CALLCENTER系统的主库导入CUSTOMER数据的时候,遇到了ORA-01555

错误。

软件环境:两台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                  TYPE                 VALUE
--------------------- -------------------- -----------------------
undo_management       string               MANUAL
undo_retention        integer              900
undo_suppress_errors  boolean              FALSE
undo_tablespace       string               UNDOTBS1

undo_management

      回滚段的管理方式。值可以为MANUAL/AUTO9i中默认是MANUAL10g中默认是AUTO

      9i后,回滚段就以表空间的形式管理,并且支持系统自动管理回滚段。一个回滚表空间上可以创建多个回滚段,一个数据库可以创建多个回滚表空间。但是,一个实例(Instance)只能使用一个回滚表空间。

如果undo_management设置为MANUAL,就是手动创建回滚段

SQL> create rollback segment undo1 tablespace UNDOTBS1;

      如果设置为AUTOOracle就自动管理回滚段的创建,而手工创建就会失败。

undo_retention

      这个参数设置回滚段中的被提交或回滚的数据强制保留时间,单位是秒。请注意,这个参数和1555错误有非常大的关系。但是,需要提醒的是,并不是回滚段中的数据超过这个时间以后就会被清除掉,而是等到后面事务产生的回滚数据覆盖掉“超期”数据。所以这就是为什么我们往往看到系统的回滚表空间占有率始终是100%的原因了。

undo_suppress_errors

      是否报与回滚段有关的错误。如果为FALSE,就不会产生与回滚段有关的错误。但是,请注意,并不是不会发生回滚段错误,而只是屏蔽错误信息,错误发生了就会存在滴。在10g中,这个参数是隐含参数。

undo_tablespace

      为每个实例制定的唯一当前使用的回滚段表空间。

面我们就模拟一下1555错误发生的情况:

首先建立测试环境。由于我们只是要模拟1555错误的发生,所以需要建立一个小的回滚表空间,并且设置undo_retention时间为1(秒),以便回滚数据尽快被覆盖(呵呵,要防止1555错误发生,这就一定要避免的)。

 

CREATE UNDO TABLESPACE rbs_ts
DATAFILE 'rbs_ts2.dbf' SIZE 10M AUTOEXTEND OFF;
 
alter system set undo_retention=1 scope=spfile;
 
alter system set undo_management=auto scope=spfile;
 
alter system set undo_tablespace=rbs_ts scope=spfile;
 
startup force
 
alter tablespace rbs_ts online;
 
create table demo.t_dual as select * from dual;
 
insert into t_dual values(1);
 
commit;
 

 

一致性读导致1555错误

开始读取表。

SQL>
SQL> var cl refcursor
SQL> begin
  2  open :cl for select * from demo.t_multiver;
  3  end;
  4  /
 
PL/SQL procedure successfully completed.
 
SQL>

 

更新表数据,产生回滚信息

SQL> update demo.t_multiver set b = 111 where a = 1;
 
1 row updated.
 
SQL> commit;
 
Commit complete.
 

 

运行大批其他事务,充满所有回滚段,以致覆盖上面的回滚信息回滚段可以通过dba_rollback_segs查看。

SQL> begin
  2    for i in 1..20000 loop
  3      update demo.t_dual set dummy=1;
  4      commit;
  5    end loop;
  6  end;
  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> var cc refcursor
SQL>
SQL> begin
  2  open :cc for select * from t_multiver;
  3  end;
  4  /
 

 

这时一个事务更新了该数据块,但在提交前,我们手工将buffer cache中的数据做了flush,再做提交。这时的数据块上只记录了锁标志,没有事务标志和Commit SCN

PL/SQL procedure successfully completed.
 
SQL>
SQL> update t_multiver set b=115 where a=1;
 
1 row updated.
 
SQL>
SQL> alter system flush buffer_cache;
 
System altered.
 
SQL>
SQL> commit;
 
Commit complete.
 

 

进行非常多的事务,将回滚段中的事务信息表中的数据全部覆盖:

SQL>
SQL> begin
  2    -- overwrite rollback slot
  3    for i in 1..40000 loop
  4      update t_dual set dummy=1;
  5      commit;
  6    end loop;
  7  end;
  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 SEGMENT rollback_segment

给大事务指定回滚段,即降低大事务回滚信息覆盖其他事务的回滚信息的几率,又降低了他自身的回滚信息被覆盖的几率。大事务的存在,往往是1555错误产生的诱因。

6、使用游标时尽量使用显式游标,并且只在需要的时候打开游标,同时将所有可以在游标外做的操作从游标循环中拿出。

当游标打开时,查询就开始了,直到游标关闭。减少游标的打开时间,就减少了1555错误发生的几率。

在本次操作中,笔者的解决方案是:

1.适当增大undo表空间的尺寸,防止回滚信息被覆盖。

2.增加undo_retention时间,增加到10800秒(在导入源和导出源都修改)。

3.删除目标表的部分索引,加快导入速度,在倒完数据后,再建立。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8183550/viewspace-663171/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/8183550/viewspace-663171/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
kettle ora-01555是指在使用kettle工具进行数据抽取或转换时,出现了Oracle数据库ORA-01555错误ORA-01555错误Oracle数据库的一个常见错误,也被称为Snapshot too old错误ORA-01555错误是由于事务回滚中的数据被其他事务重用或者已经被覆盖而致的。这种情况通常发生在并发事务环境下,当一个事务需要读取某些数据,但是在读取期间该数据已经被其他事务修改或删除,致该事务无法读取到所需的数据而出现ORA-01555错误。 在kettle中,当进行数据抽取或转换时,kettle会同时执行多个SQL语句以读取或修改数据库中的数据。如果在执行这些SQL语句的过程中,有其他事务修改了这些数据,那么就有可能ORA-01555错误的发生。 为了解决ORA-01555错误,可以考虑以下几个方案: 1. 增加Rollback的大小:可以通过增大回滚的大小来解决ORA-01555错误。通过增加回滚的大小,可以延长数据被重用的时间,从而减少ORA-01555错误的发生。 2. 设置合适的UNDO_RETENTION参数:可以通过设置UNDO_RETENTION参数来控制回滚数据的保留时间。增加UNDO_RETENTION的值可以延长数据被重用的时间,减少ORA-01555错误的发生。 3. 调整事务隔离级别:可以尝试调整事务的隔离级别,例如将隔离级别改为READ_COMMITTED,可以降低ORA-01555错误的发生概率。 此外,还可以根据具体情况进行其他的优化措施,例如优化SQL语句、调整并发事务的执行顺序等,以减少ORA-01555错误的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值