[SQL]Oracle ORA-01555快照过旧的错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SQL]Oracle ORA-01555快照过旧的错误相关的知识,希望对你有一定的参考价值。

参考技术A

关于Oracle ORA-01555快照过旧的错误
首先了解Oracle在什么情况下会产生ORA-01555错误:

假设有一张6000万行数据的testdb表,预计testdb全表扫描1次需要2个小时,参考过程如下:
1、在1点钟,用户A发出了select * from testdb;此时不管将来testdb怎么变化,正确的结果应该是用户A会看到在1点钟这个时刻的内容。
2、在1点30分,用户B执行了update命令,更新了testdb表中的第4100万行的这条记录,这时,用户A的全表扫描还没有到达第4100万条。毫无疑问,这个时候,第4100万行的这条记录是被写入了回滚段,假设是回滚段UNDOTS1,如果用户A的全表扫描到达了第4100万行,是应该会正确的从回滚段UNDOTS1中读取出1点钟时刻的内容的。
3、这时,用户B将他刚才做的操作提交了,但是这时,系统仍然可以给用户A提供正确的数据, 为那第4100万行记录的内容仍然还在回滚段UNDOTS1里,系统可以根据SCN到回滚段里找到正确的数据,但要注意到,这时记录在UNDOTS1里的第4100万行记录已经发生了重大的改变:就是第4100万行在回滚段UNDOTS1里的数据有可能随时被覆盖掉, 为这条记录已经被提交了!
4、由于用户A的查询时间漫长,而业务在一直不断的进行,UNDOTS1回滚段在被多个不同的transaction使用着,这个回滚段里的extent循环到了第4100万行数据所在的extent,由于这条记录已经被标记提交了,所以这个extent是可以被其他transaction覆盖掉的!
5、到了1点45分,用户A的查询终于到了第4100万行,而这时已经出现了第4条说的情况,需要到回滚段UNDOTS1去找数据,但是已经被覆盖掉了,这时就出现了ORA-01555错误。
原因分析:"报表"程序执行时间漫长,在程序查询的过程中其他用户对"报表"进行了更新,被更新的数据写入了回滚段,当程序到回滚段找数据时,发现数据已经被覆盖掉,于是就出现了ORA-01555错误。另外"报表"程序执行效率不高也会造成ORA-01555错误。
解决办法:
1、扩大回滚段, 为回滚段是循环使用的,如果回滚段足够大,那么那些被提交的数据就能保存足够长的时间,使那些大事务完成一致性读取。之前EBS系统UNDO 表空间 为9GB,目前为10GB。
2,强制走索引,如果sql语句用了索引字段,在执行过程中没有走上索引,需要强制走索引,merge 语句强制走索引,如 merge 和selec 的语句
MERGE/ +INDEX(F,IDX_S01_T_EXW_BASIC_DOCUMENTNO) /
INTO BI_DM.S01_T_INFOR F
USING (SELECT/ +INDEX(IDX_OMS_WH_OUTB_ORD_REBATE_02) / T12.ORDER_NO, T12.IS_REBATE, T12.CREATED, T12.UPDATED
FROM BI_ODS.OW_ORD_REBATE T12
WHERE T12.UPDATED >= DATA_DATE_3D
AND T12.IS_ACTIVE = \'Y\'
AND T12.IS_DELETE = \'N\') S
ON (F.OVERSEAS_WAREHOUSE_ID = VI_WAREHOUSE_ID AND F.DOCUMENTNO = S.ORDER_NO AND F.DATA_SOURCE = \'OW\')
WHEN MATCHED THEN
UPDATE SET F.REBATE_STATUS = S.IS_REBATE;

ORACLE SQL优化之ORA-03150&ORA-02055&ORA-02063

   今天,一实施同事反应,他执行一存储过程,执行到一条含有dblink的insert into select语句时报错:ORA-03150 ORA-02055 ORA-02063,具体报错如图所示:

技术分享

该报错涉及的SQL语句是:

insert into [email protected]_jkb
  select oae001,
         akb020,
         akc190,
         akc220,
         aae072,
         akc515,
         aka135,
         aae100,
         akc301,
         b.reject_money,
         b.reject_reson,
         b.oper_user_id,
         b.oper_user_name,
         b.oper_date,
         ‘0‘,
         ‘EH‘,
         ‘EH‘,
         sysdate,
         null,
         null
    from KC22 a
   inner join dr_audit b
      on a.oae001 = b.prescription_no
     and b.load_date > (select syncdate from dr_syncdate)
     and a.aae100 = ‘1‘;

以下是优化的处理过程:

1、首先,让其统计了insert into select的select的数据量有3394条,不是太多,但是在执行insert into子查询select的时候过程很长,有10多分钟;

2、查看insert into子查询的sql执行计划,如下:

技术分享

3、让实施同事控制子查询的数据量为1条时,虽然执行时间比较长,但是能够执行成功

4、建议实施同事,根据select子句的where条件对表kc22的字段AAE100创建了索引,索引创建后,子查询语句执行速度明显提升,执行计划如下:

技术分享

5、然后,实施同事再次执行insert into select,2分钟左右成功执行。

问题解决!


本文出自 “清风艾艾” 博客,请务必保留此出处http://3596022.blog.51cto.com/3586022/1976244

以上是关于[SQL]Oracle ORA-01555快照过旧的错误的主要内容,如果未能解决你的问题,请参考以下文章

Oracle数据库 ORA-01555快照过旧是怎么回事?怎么解决?

Oracle ORA-01555 快照过旧 说明

Oracle ORA-01555 快照过旧 说明

Oracle数据库 ORA

Oracle数据库 ORA

ORA-01555: 快照太旧: 名为 "" 的回滚段号太小