为什么我们在 Oracle SQL 中需要 SELECT FOR UPDATE?

问题描述 投票:0回答:1

数据库将通过克服读写冲突(使用锁定)自动找出如何并行处理两个或多个事务(作为可序列化的计划)。默认情况下,它们之间是隔离的。

那么为什么我们还需要使用像

SELECT FOR UPDATE
这样的语句来锁定数据库中的任何数据呢?为什么我们不能在交易块中进行我们想要的任何操作?

Begin transaction
//queries
//commit
End transaction
sql oracle relational-database oracle12c
1个回答
16
投票

为什么我们不能在交易区块中进行我们想要的任何事情?

因为在 Oracle 中,读者不会阻止作者。如果您从表中

select
,则不会锁定它并且没有事务。所以,想象一下你这样做:

select col1, col2 into l_col1, l_col2
from table1
where ...;

if (<some logic based on l_col2>) then
  update table1 set col2 = something where col1 = l_col1;
end if;

没关系;但如果两个会话同时运行该代码,一个会话可能会更新行之间另一个会话选择并执行其更新 - 导致更新丢失或逻辑不正确,因为状态实际上并不符合预期。

如果你这样做

select ... for update

select col1, col2 into l_col1, l_col2
from table
where ...
for update;  -- or: for update of col2

if (<some logic based on l_col2>) then
  update table1 set col2 = something where col1 = l_col1;
end if;

然后从表中选择的行被第一个会话锁定,因此第二个会话必须等待该事务完成才能获得锁定,并且它将看到该事务的状态第 after

 行已应用第一次更新。没有丢失更新,没有混乱。
您还可以锁定不想更新的行,如文档

所述:

带有

select for update
子句(

SELECT

 语句)的 
FOR UPDATE
 语句选择结果集的行并锁定它们。 
SELECT FOR UPDATE
 允许您基于行中的现有值进行更新,因为它确保在您更新这些值之前没有其他用户可以更改这些值。您还可以使用 
SELECT FOR UPDATE
 锁定不想更新的行,如示例 9-6 所示。
你可以调整行为:

默认情况下,

SELECT FOR UPDATE
语句会等待,直到获取请求的行锁。要更改此行为,请使用

SELECT FOR UPDATE

 语句的 
NOWAIT
WAIT
SKIP LOCKED
 子句。有关这些子句的信息,请参阅 
Oracle 数据库 SQL 语言参考
如果

SELECT FOR UPDATE
位于光标循环中,那么它还允许您执行以下操作

select for update

update table1 set col2 = something where current of <cursor>;
与显式光标关联时,该光标称为

SELECT FOR UPDATE

 光标。只有 
FOR UPDATE
 游标可以出现在 
FOR UPDATE
CURRENT
 语句的 
UPDATE
 OF 子句中。 (
DELETE
 子句是 SQL 语句 
CURRENT OF
WHERE
UPDATE
 子句的 PL/SQL 扩展,将语句限制为游标的当前行。)
游标查询选择的行在获取时被锁定。 (但桌子本身没有锁定。)

© www.soinside.com 2019 - 2024. All rights reserved.