2012-03-04 25 views
7

在Oracle SQL更新語句中,假設更新會影響5行,update語句是否同時或順序更新所有5行?例如。在Oracle SQL更新語句中,行更新是否同時發生?

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

在上述語句中,將指數1至5中的序列被更新,即,1,2,3,4,然後5以上,否則會同時發生(1-5一次全部)。

我已經提到Oracle documentation但似乎沒有提到這一點。

+0

從邏輯上講,它們同時發生。在實踐中,他們不這樣做,但是你將無法發現差異。如果您執行UPDATE Table 1 SET Index = Index + 1 WHERE INDEXE BETWEEN 1 AND 5',它會變得更有趣。 – 2012-03-04 06:53:58

回答

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

您提供的鏈接確實覆蓋了這一點。 Oracle始終強制執行語句級別的讀取一致性 - 這意味着對table1的任何查詢都不會返回某些更新的記錄,有些則不會。這將是全部或全部,無論隔離級別如何。

+0

謝謝。爲了進一步澄清,假設索引4有一個讀鎖,更新語句是否會等待讀鎖解除以更新所有5行? – Ted 2012-03-04 06:19:31

+0

@Ted:在Oracle中,讀者和作者不會互相阻礙。數據更新時,舊數據會自動保存一段時間(UNDO)。這允許查詢在某個時間點讀取數據,而不管正在發生什麼變化。 – 2012-03-04 06:35:24

+0

@jonearles是的,但是編寫者**會互相阻塞(當他們寫入相同的行時)。編寫者將逐行鎖定,這意味着如果所有事務的寫入都不以相同順序完成,則存在潛在的死鎖問題。由於UPDATE沒有ORDER BY子句,必須使用單獨的'SELECT ... ORDER BY ... FOR UPDATE'來保證鎖定順序。 – 2012-03-04 17:18:47

4

也可能是。

在這種情況下,由於您只更新了5行,因此並行DML將不太可能適用。假設UPDATE不調用並行DML,行將按順序更新,儘管行更新的順序是任意的。 INDEX 1可能是第一個被更新,最後一個被更新,或者它可能在中間被更新。這取決於查詢計劃。

2

UPDATE,DELETE和INSERT沒有定義的順序。從概念上講,他們適用於一套,一次完成。實際上,不要依賴任何你可能觀察到的序列 - 它是一個可以改變的實現細節,而只是因爲現實世界妨礙了理論而發生。

+0

謝謝!我推斷更新是基於集合的方式完成的,即更新將在執行更新語句之前等待所有行可用。 – Ted 2012-03-04 06:21:22

+0

@Ted:Oracle會執行塊級鎖定,但在更新開始時不必解鎖所有行。 – jmoreno 2012-03-04 07:44:15

0

所有記錄將在一次交易中更新爲一條記錄。 Oracle不保證更新順序中的任何順序。

您可以通過您表中的dbms_transaction.local_transaction_id值更新任何字段以進行檢查。