问题描述:
在执行下面语句时曝出了标题所示的错误ORA-01555。
INSERT INTO super.sb_kpxx_com
select
*
from SUPER.SB_KPXX a
where KPRQ >= TO_DATE('20130101', 'yyyymmdd') and kprq <=TO_DATE('20131001','yyyymmdd') and not exists (select
1
from SUPER.SB_KPXX@SCDB.GZDS.GOV.CN b
where a.SB_NUM = b.SB_NUM
AND a.KPLSH = b.KPLSH
AND a.DWID = b.DWID);
分析:
这个SQL语句的意思是将明细库中的多余数据(相对于生产库来说)插入到临时表中进行备份。
百度了一下可能出错的原因:
1) 你建立表的时候pctversion参数太小了,而你的查询数据过大,超出了它的范围。 ORACLE一次处理不了那么多的数据,要更改参数。
由于不懂pctversion,于是又去百度了一下,发现了如下信息:
PCTVERSION 、RETENTION:都是ORACLE用来管理LOB字段镜像数据的。在LOB 数据的更新过程中,
ORACLE没有用UNDO TABLESPACE空间,而是从LOB字段所在的表空间里划分一段空间来做镜像空间的,
这个空间的大小由PCTVERSION参数控制,默认值为10,代表划分表空间的10%作为镜像空间,
每个镜像空间的单元大小由CHUNK参数指定,pctversion可以使用在manual undo mode和automatic undo mode 环境中.
retention应用了automatic undo mode中的undo_retention通过时间来管理lob镜像空间.
pctversion和retention不能同时被指定.建议数据库在automatic undo mode下使用retention参数。(关于retention可以查看如下链接:http://blog.sina.com.cn/s/blog_62defbef0101o9iv.html);
上面关键的地方是说pctversion和retention不能同时被指定,所以我用show parameter undo_retention查看undo_retention参数:
NAME TYPE VALUE
-------------- ----- -----
undo_retention integer 18000
18000/3600=5个小时,而操作报错大概是一小时以内,所以这个原因不太可能。
2)你查询的时候有人做了更新操作,导致你刚开始查询的数据相比更新过后的数据旧了。-->也就是快照过旧
这个原因是有可能的,我曾在不同的时间段查询,发现数据由92条增加到了207条,原因是因为我直接在明细库中进行查询操作,而工作日会有业务,明细库中的数据是会发生变化的。一旦我插入的数据发生了变化,便会有这个错误。这个尚未得到认证。
如果是第一种情况网上有如下解决方案:
1)可以考虑多个分段查询where sendtime between xx and xxx,这样就不会太大.。(针对pctversion模式)
2) 增加适当的索引缩短查询时间(针对retention模式 )