在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但似乎沒有提到這一點。
在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但似乎沒有提到這一點。
執行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;
/
您提供的鏈接確實覆蓋了這一點。 Oracle始終強制執行語句級別的讀取一致性 - 這意味着對table1的任何查詢都不會返回某些更新的記錄,有些則不會。這將是全部或全部,無論隔離級別如何。
謝謝。爲了進一步澄清,假設索引4有一個讀鎖,更新語句是否會等待讀鎖解除以更新所有5行? – Ted 2012-03-04 06:19:31
@Ted:在Oracle中,讀者和作者不會互相阻礙。數據更新時,舊數據會自動保存一段時間(UNDO)。這允許查詢在某個時間點讀取數據,而不管正在發生什麼變化。 – 2012-03-04 06:35:24
@jonearles是的,但是編寫者**會互相阻塞(當他們寫入相同的行時)。編寫者將逐行鎖定,這意味着如果所有事務的寫入都不以相同順序完成,則存在潛在的死鎖問題。由於UPDATE沒有ORDER BY子句,必須使用單獨的'SELECT ... ORDER BY ... FOR UPDATE'來保證鎖定順序。 – 2012-03-04 17:18:47
也可能是。
在這種情況下,由於您只更新了5行,因此並行DML將不太可能適用。假設UPDATE
不調用並行DML,行將按順序更新,儘管行更新的順序是任意的。 INDEX
1可能是第一個被更新,最後一個被更新,或者它可能在中間被更新。這取決於查詢計劃。
所有記錄將在一次交易中更新爲一條記錄。 Oracle不保證更新順序中的任何順序。
您可以通過您表中的dbms_transaction.local_transaction_id值更新任何字段以進行檢查。
從邏輯上講,它們同時發生。在實踐中,他們不這樣做,但是你將無法發現差異。如果您執行UPDATE Table 1 SET Index = Index + 1 WHERE INDEXE BETWEEN 1 AND 5',它會變得更有趣。 – 2012-03-04 06:53:58