2

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

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

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

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

    1. 是的:如果我为每一行做一个真正繁重的过程,数据将在很长一段时间内不可用......

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

非常感谢。

4

1 回答 1

3

您可能想阅读概念指南中有关数据并发和一致性的部分。

您的具体问题的答案:

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

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

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

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

您的游标不会看到这些更改,它会继续处理打开游标时存在的行。

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

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

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

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

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

于 2012-04-10T11:28:34.697 回答