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

发布于 2024-12-10 20:02:46 字数 862 浏览 0 评论 0原文

可以说我有如下代码:

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;

如果是这样,我希望发生的情况是将 select 语句“锁定”T,因此无法对其进行修改。

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

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。

Lets say I've got code like the following:

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

Am I correct in saying that by the time (2) executes, whatever has been selected from T in (1) may no longer be in T, if, for example, in another session the following executed:

delete from T where x = 42;

If so, what I would like to happen is the select statement to 'lock' T, so it can not be modified.

I realise I can do this explicitly by doing:

lock table T in exclusive mode;

But what if T is a view? Do I have to look through the definition of Ts view/subviews to find all tables it references and lock them individually, or can I do something like this:

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

Where START_TRANSACTION ensures locks all tables referred to in all select statements until the transaction is complete?

Or is there another nicer solution to this issue? I'm using Oracle 10g if that is important.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你的笑 2024-12-17 20:02:46

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

因此,您可以通过执行以下操作来锁定行...

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

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

Am I correct in saying that by the time (2) executes, whatever has
been selected from T in (1) may no longer be in T

Yes.

So you can lock the row by doing...

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

You can optionally use NOWAIT to make the statement fail if someone else already has the row locked. Without the NOWAIT the statement will pause until it can lock the row.

剩一世无双 2024-12-17 20:02:46

您需要使用 select ... for update 变体,如图 此处

尽管锁定视图是有效的,但您绝对不想想要锁定整个表。来自 Oracle 文档

当对视图发出 LOCK TABLE 语句时,基础基表将被锁定。

然而,这可能会成为性能杀手,您的 DBA找到您 - 无处可藏:-)

You need to use the select ... for update variation as shown here.

You definitely don't want to lock the entire table, although locking a view is valid. From the Oracle docs:

When a LOCK TABLE statement is issued on a view, the underlying base tables are locked.

However, that may be a performance killer and your DBAs will find you - there's nowhere to hide :-)

∞梦里开花 2024-12-17 20:02:46

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

I'm pretty sure that transaction are exactly what you want here. The help enforce what's called ACID for a sequence of operations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文