创建游标,是否正在复制数据?

时间:2012-04-10 10:52:05

标签: database oracle cursor

我现在正在使用游标,这对我来说变得一团糟,希望你能向我强调一些问题。

我已经检查了有关游标的oracle文档,但我找不到:

打开游标时,是否是在内存中创建的结果的本地副本?

  • 是的:如果我有一张包含大量数据的表格,这真的有意义吗?我认为它不会真正有效,不是吗?。
  • 没有: 整个数据是否锁定到其他进程?

    1. YES :如果我为每一行做一个真正繁重的过程怎么办,那么这些数据将会持续很长时间......

    2. NO :如果另一个进程修改了我当前正在使用光标的数据,或者如果它添加了新行,会为光标更新它会发生什么?

非常感谢。

1 个答案:

答案 0 :(得分:3)

您可能需要阅读Data Concurrency and ConsistencyConcepts Guide上的部分。

您特定问题的答案:

  

打开游标时,是创建结果的本地副本   存储器?

不,但是通过Oracle的“多版本读取一致性”(参见上面的链接),游标提取的行将与光标打开的时间点一致 - 即获取的每一行都是一行当光标打开并且仍具有相同的值时存在(即使另一个会话可能已更新甚至同时删除它)。

  

否:整个数据是否已锁定到其他进程?

没有

  

否:如果另一个进程修改了我当前正在使用光标的数据,或者如果它添加了新行,会为光标更新它会发生什么?

您的光标不会看到这些更改,它会继续使用光标打开时存在的行。

“概念指南”详细解释了这一点,但其工作方式的实质如下:

  • Oracle维护着一个名为System Change Number (SCN)的东西,它不断增加。
  • 当光标打开时,它会记下SCN的当前值。
  • 当光标获取行时,它会查看标记在其上的SCN。如果此SCN与光标的起始SCN相同或更低,则数据是最新的并被使用。但是,如果行的SCN高于游标的那么这意味着另一个会话已经更改了行(并提交了更改)。在这种情况下,Oracle在回滚段中查找旧版本的行并使用它。如果查询运行很长时间,则旧版本可能已在回滚段中被覆盖。在这种情况下,查询失败并显示ORA-01555错误。

如果需要,您可以修改此默认行为。例如,如果在游标运行期间没有其他会话修改您正在查询的行是至关重要的,那么您可以使用FOR UPDATE子句来锁定行:

CURSOR c IS SELECT sal FROM emp FOR UPDATE OF sal;

现在,任何尝试修改查询中运行的行的会话都将被阻止,直到您的查询完成提交或回滚为止。