在Oracle SQL更新语句中,行更新是否同时发生?

时间:2012-03-04 06:02:33

标签: database oracle concurrency sql-update

在Oracle SQL更新语句中,假设更新会影响5行,update语句是否会同时或按顺序更新所有5行? E.g。

UPDATE table1 
set column2 = 'completed' WHERE
index between 1 AND 5

在上面的陈述中,索引1到5会按顺序更新,即1,2,3,4然后5,或者它会同时发生(1-5同时发生)。

我曾提到Oracle documentation,但似乎没有提到这一点。

5 个答案:

答案 0 :(得分:4)

潜在的。

在这种情况下,由于您只是更新了5行,因此并行DML非常不合适。假设UPDATE不调用并行DML,则行将按顺序更新,但更新行的顺序是任意的。 INDEX 1可能是第一个要更新,最后一个要更新,或者可以在中间更新。这取决于查询计划。

答案 1 :(得分:4)

执行UPDATE语句后,语句的效果将对事务的其余部分可见(如果提交,则对其他事务可见)。 Oracle实际执行的顺序是实现细节(类似地,不保证SELECT结果的顺序除非指定ORDER BY)。


在大多数情况下,此订单对客户来说无关紧要。一种情况可能是避免与另一个更新重叠行集的事务发生死锁。 UPDATE将锁定正在更新的行,直到事务结束,因此如果两个事务尝试锁定相同的行,但顺序不同,则可能会出现死锁。

避免死锁的标准方法是始终锁定明确定义的顺序。不幸的是,UPDATE没有ORDER BY子句,但你可以这样做:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT ... WHERE condition ORDER BY ...  FOR UPDATE;
UPDATE ... WHERE condition;
COMMIT;

两个语句的condition相同。可序列化隔离级别是WHERE始终在两个语句中看到相同行集所必需的。

或者,在PL / SQL中你可以这样做:

DECLARE
    CURSOR CUR IS SELECT * FROM YOUR_TABLE WHERE condition ORDER BY ... FOR UPDATE;
BEGIN
    FOR LOCKED_ROW IN CUR LOOP
        UPDATE YOUR_TABLE SET ... WHERE CURRENT OF CUR;
    END LOOP;
END;
/

答案 2 :(得分:2)

您提供的链接确实涵盖了这一点。 Oracle总是强制执行语句级读取一致性 - 这意味着对table1的查询不会返回一些更新的记录,而有些则不会。无论隔离级别如何,它都将是全部或全部。

答案 3 :(得分:2)

UPDATE,DELETE和INSERT没有已定义的订单。从概念上讲,它们适用于一组并且一次完成。实际上,不要依赖于你可能观察到的任何序列 - 这是一个可以改变的实现细节,只有因为现实世界妨碍理论才会发生。

答案 4 :(得分:0)

所有记录将在一次交易中更新为一条记录。 Oracle不保证更新顺序中的任何顺序。

您可以通过表中的dbms_transaction.local_transaction_id值更新任何字段以进行检查。