Oracle

在更新期間鎖定 Oracle 中的記錄

  • June 7, 2013

我遇到了一個死鎖問題,很容易通過更改應用程序邏輯來解決,但我的印像是 Oracle 的行為會有所不同,而且死鎖永遠不會發生。例如,我有兩張桌子

table1( table1_id (PK), num1, num2);
table2(table2_id(PK), table1_id(FK to table1,indexed), low_cardinality_column, num3, num4);

表 2 還具有更新( ) 的行級after update觸發器。table1.num``table1.num1 = table1.num1 + :NEW.num3 where table1.table1_id = :NEW.table1_id

第一個程序執行UPDATE table2 set num3 =1 where low_cardinality_column =:bind_var(沒有索引low_cardinality_column,通常影響數千條記錄)。

第二個程序在一個事務中更新 table2 和 table1

UPDATE table2 
  SET num4 = :bind_var4 
WHERE table2_id = :bind_var_id 
RETURNING table1_id INTO :out_var

UPDATE table1 
 SET num2 = :new_num2_val 
WHERE table1_id = :out_var

如果它們碰巧同時執行,跟踪顯示這兩個程序之間存在相當多的死鎖,我對此有點困惑。table1我知道如果第二個程序以相反的順序更新表(然後),肯定會發生死鎖table2,但在這種特殊情況下,我認為引擎實際上不會開始更新,直到它在必須更新的每條記錄上獲得 RX 鎖定(因此一個程序會等待另一個程序完成)。如果不能保證,那麼死鎖的解釋很明顯:Process1以未定義的順序鎖定記錄,而Process 2碰巧更新了table2尚未鎖定的行並嘗試更新table1已經由Process 1更新的行。如果是SQLServer I 100% 肯定是這樣,但我對 Oracle 還是很陌生……

我想知道是否有人可以澄清這個問題。謝謝你。如果這很重要,我會使用 10g。

您是對的:程序 2 從 Table2 上的 update 開始,但在 Table1 上遇到了 update 死鎖,因為該行正在由程序 1 更新(尚未送出)。

您假設數據庫“知道”它將在程序 2 中遇到死鎖並且會否認事務是錯誤的。數據庫不知道事務中的未來語句,因此它無法避免死鎖。

引用自:https://dba.stackexchange.com/questions/44021