Has*_*ake 6 sql oracle relational-database oracle12c
数据库将通过克服读写冲突(使用锁定)自动找出如何并行处理两个或多个事务(作为可序列化的计划)。默认情况下,它们之间是隔离的。
那么为什么我们仍然需要使用类似这样的语句来锁定数据库中的任何数据呢SELECT FOR UPDATE?为什么我们不能在交易块中进行我们想要的任何操作?
Begin transaction
//queries
//commit
End transaction
Run Code Online (Sandbox Code Playgroud)
Ale*_*ole 13
为什么我们不能在交易块中进行我们想要的任何操作?
因为在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;
Run Code Online (Sandbox Code Playgroud)
没关系; 但是,如果两个会话同时运行该代码,一个会话可能会更新另一个会话选择和执行其更新之间的行- 导致更新丢失或逻辑不正确,因为状态实际上并不符合预期。
如果你这样做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;
Run Code Online (Sandbox Code Playgroud)
那么从表中选择的行被第一个会话锁定,因此第二个会话必须等待该事务完成才能获得锁,并且它将在第一次更新后select for update看到该行的状态应用。没有丢失更新,没有混乱。
您还可以锁定不想更新的行,如文档所述:
SELECT带有子句(FOR UPDATEstatementSELECT FOR UPDATE)的语句选择结果集中的行并锁定它们。SELECT FOR UPDATE允许您基于行中的现有值进行更新,因为它可以确保在您更新这些值之前没有其他用户可以更改这些值。您还可以使用它SELECT FOR UPDATE来锁定不想更新的行,如示例 9-6 所示。
你可以调整行为:
默认情况下,该
SELECT FOR UPDATE语句会等待,直到获取请求的行锁。要更改此行为,请使用语句的NOWAIT、WAIT或SKIP LOCKED子句SELECT FOR UPDATE。有关这些子句的信息,请参阅 Oracle 数据库 SQL 语言参考。
如果select for update位于游标循环中,那么它还允许您执行以下操作
update table1 set col2 = something where current of <cursor>;
Run Code Online (Sandbox Code Playgroud)
当
SELECT FOR UPDATE与显式游标关联时,该游标称为游标FOR UPDATE。只有FOR UPDATE游标可以出现在or语句CURRENT的 OF 子句中。(该子句是SQL 语句和的子句的PL/SQL 扩展,将语句限制为游标的当前行。)UPDATEDELETECURRENT OFWHEREUPDATEDELETE
游标查询选择的行在获取时被锁定。(但是表本身没有被锁定。)
| 归档时间: |
|
| 查看次数: |
29088 次 |
| 最近记录: |