如何锁定选择,而不仅仅是插入/更新/删除

时间:2011-10-19 06:36:48

标签: sql database oracle locking

让我们说我有以下代码:

begin
  select ... from T where x = 42;         -- (1)
  .
  .
  .
  update T ... where x = 42;              -- (2)
  commit;
end;

我是否正确地说,在执行时间(2)时,从(1)中的T中选择的任何内容可能不再在T中,例如,如果在另一个会话中执行以下操作:

delete from T where x = 42;

如果是这样,我想要发生的是'锁定'T的select语句,因此无法修改。

我意识到我可以通过以下方式明确地做到这一点:

lock table T in exclusive mode;

但如果T是一个视图怎么办?我是否必须查看T视图/子视图的定义以查找它引用的所有表并单独锁定它们,或者我可以执行以下操作:

begin
  START_TRANSACTION;
  select ... from T where x = 42;         -- (1)
  .
  .
  .
  update T ... where x = 42;              -- (2)
  commit;
end;

START_TRANSACTION确保在事务完成之前锁定所有select语句中引用的所有表?

还是有另一个更好的解决方案吗?如果这很重要,我正在使用Oracle 10g。

3 个答案:

答案 0 :(得分:5)

  

我是否正确地说,到时候(2)执行,无论有什么   从(1)中的T中选择可能不再是T

所以你可以通过......来锁定行。

SELECT ...
[INTO   ...]
FROM   T
WHERE  x = 42
FOR    UPDATE [NOWAIT];

如果其他人已经锁定了行,您可以选择使用NOWAIT使语句失败。如果没有NOWAIT,语句将暂停,直到它可以锁定该行。

答案 1 :(得分:2)

您需要使用here所示的select ... for update变体。

你肯定想要锁定整个表,尽管锁定视图是有效的。来自Oracle docs

  

在视图上发出LOCK TABLE语句时,底层基表将被锁定。

然而,这可能是一个性能杀手,而你的DBA 找到你 - 无处可隐藏: - )

答案 2 :(得分:0)

我很确定交易正是你想要的。该帮助强制执行一系列操作所谓的ACID