最近又是连续几天和bug打交道。其实ORA-1555错误应该是比较常见的错误信息,在回滚段自动管理模式下,如果查询的运行时间超过了初始化参数UNDO_RETENTION的设置,就可能导致这个问题。
不过这个错误比较奇怪,出错SQL的执行时间居然是0秒:
Wed Mar 25 01:19:28 2009
ORA-01555 caused by SQL statement below (SQL ID: 5t3djd7212nsm, Query Duration=0 sec, SCN: 0x0002.144867d3):
Wed Mar 25 01:19:28 2009
SELECT /*+ */ DISTINCT "A1"."PURCHASE_ID" FROM "CENTER"."MLOG$_ORD_PURCHASE" "A1" WHERE "A1"."PURCHASE_ID"<>ALL (SELECT "A2"."PURCHASE_ID" FROM "CENTER"."ORD_PURCHASE" "A2" WHERE "A1"."PURCHASE_ID"="A2"."PURCHASE_ID") AND "A1"."SNAPTIME$$">:1 AND "A1"."DMLTYPE$$"<>'I'
从这个错误信息可以看出两点,除了前面提到的查询时间为0秒这个信息外,第二点就是这个SQL是系统发出的SQL。而且是系统在执行物化视图刷新时,从基表和物化视图日志中获取需要刷新的数据时,出现的错误。
这个错误发生在主站点,在对应的目标站点,可以看到对应的错误信息:
Errors in file /u1/oracle/admin/repdb01/bdump/repdb01_j002_6026.trc:
ORA-12012: error on auto execute of job 1
ORA-12008: error in materialized view refresh path
ORA-01555:快照过旧:回退段号20 (名称为"_SYSSMU20$")过小ORA-02063: preceding line from NEWTRADE
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 794
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 851
ORA-06512: at "SYS.DBMS_IREFRESH", line 683
ORA-06512: at "SYS.DBMS_REFRESH", line 195
ORA-06512: at line 1
其实如果只是SQL查询时间为0,且产生ORA-1555错误,这个问题倒是碰到过,在9i中指定一个过早的TIMESTAMP进行闪回查询,就会引发这个错误:
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for Linux: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production
SQL> SELECT COUNT(*) FROM TEST;
COUNT(*)
----------
31400
SQL> SELECT COUNT(*) FROM TEST AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' DAY);
SELECT COUNT(*) FROM TEST AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' DAY)
*
ERROR位于第1行:
ORA-01555:快照过旧:回退段号5在名称为"_SYSSMU5$"过小
这时后台就会出现查询时间为0的ORA-1555错误:
Wed Mar 25 16:49:24 2009
ORA-01555 caused by SQL statement below (Query Duration=0 sec, SCN: 0x0000.a5f572cc):
Wed Mar 25 16:49:24 2009
SELECT COUNT(*) FROM TEST AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' DAY)
不过这种报错方式在10g中已经有了改变:
SQL> SELECT COUNT(*) FROM T_NUMBER;
COUNT(*)
----------
2
SQL> SELECT COUNT(*) FROM T_NUMBER AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' DAY);
SELECT COUNT(*) FROM T_NUMBER AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' DAY)
*
ERROR at line 1:
ORA-08180: no snapshot found based on specified time
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
而当前的环境是10g的,且并没有执行AS OF查询,所以出现这个错误就很奇怪了。
检查系统中UNTO_RETENTION的设置:
bash-3.00$ sqlplus "/ as sysdba"
SQL*Plus: Release 10.2.0.3.0 - Production on星期三3月25 16:18:46 2009
Copyright (c) 1982, 2006, Oracle. All Rights Reserved.
连接到:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP and Data Mining options
SQL> show parameter undo_
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS2
虽然数据库中UNDO_RETENTION的设置并不长,但是对于支持绝大部分SQL的运行是没有问题的,何况这个SQL的运行时间是0。
查看了V$UNDOSTAT视图,没有发现重现ORA-1555错误的时间点有何异常。
搜索了一下METALINK,结果确定了是Oracle的bug:Bug No. 6799685。这个bug还处于解决的过程中,估计整个10.2版本都可能会出现这个问题。
不过这个bug不可重现,而且出现几率很低,一般第二次运行同样的SQL,就不会有问题,因此对系统影响不大。