暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 澄清 “快照太旧” 错误消息

askTom 2017-03-14
431

问题描述

嗨,
我正在浏览汤姆的书,发现 “快照太旧” 部分。在 “创建小的撤消表空间” 一节中,并运行下面的块。
下面的块生成错误消息 “快照太旧”。根据我的理解,列值在第一个查询之后位于游标c中。在循环中,完成值的提取。由于值是旧的并且已经存储在cursor中,因此循环将简单地获取存储在cursor中的值。错误是如何引发的。请解释一下。


操作 $ tkyte % ORA11GR2> 声明
光标c是
选择/* first_rows */ object_name
从t
按object_id排序;

l_object_name t.object_name % 类型;
l_rowcnt数: = 0;
开始
打开c;
循环
将c取为l_object_name;
当c % 未找到时退出;
dbms_lock.sleep( 0.01 );
l_rowcnt := l_rowcnt 1;
结束循环;
关闭c;
异常
当其他人那么
dbms_output.put_line ('rowched = '| | l_rowcnt );
加薪;
结束;
/
获取的行 = 301
声明
*
第1行的错误:
ORA-01555: 快照太旧: 带名称的回滚段号46
“_ SYSSMU46_2555494716 $” 太小
ORA-06512: 在第21行


在上述块之前,此块是从其他会话运行的

开始
for x in ( select rowid rid从t )
循环
更新设置object_name = 更低 (object_name),其中rowid = x.rid;
提交;
结束循环;
结束;
/

专家解答

游标是指向结果集的指针。打开光标标志着您打算查看该时间点的数据。它没有查询返回的值。只有当您从游标中获取数据时,您才能获得值。

这就是为什么打开光标是即时的: 它没有得到任何数据!

例如,如果您创建了一个休眠1秒的函数和一个10行表:

create or replace function f (v int)
  return int as 
begin
  dbms_lock.sleep(1);
  return v;
end;
/

drop table t purge;
create table t as
  select rownum x from dual connect by level <= 10;
复制


为t的每一行调用f的查询需要10s:

SQL> set timing on
SQL> select f(x) from t;

      F(X)
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected.

Elapsed: 00:00:10.46
复制


但是打开此查询的光标是即时的:

SQL> var c refcursor;
SQL> begin
  2    open :c for
  3      select f(x) from t;
  4  end;
  5  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.31
复制


只有当您获取游标时,Oracle数据库才会执行查询并获取值:

SQL> print :c;

      F(X)
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected.

Elapsed: 00:00:10.31
复制


所以如果在fetch时间Oracle数据库无法重建数据在您的时间opened光标 (因为撤消被覆盖或其他),你得到ORA-01555。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论