2013-04-24 84 views
3

Oracle 11.2g中存在死鎖問題。死鎖發生的一個潛在原因是從子表鎖定父表中刪除。我從oracle文檔搜索,並沒有找到任何規格這種鎖。任何解釋或參考文件將不勝感激。Oracle - 從子表鎖父表中刪除行

這是代碼。

CREATE TABLE table_parent (a NUMBER PRIMARY KEY); 
CREATE TABLE table_child (b NUMBER, a NUMBER,PRIMARY KEY (b), CONSTRAINT fk_relation FOREIGN KEY (a) REFERENCES table_parent(a)); 

INSERT INTO table_parent VALUES (1); 
INSERT INTO table_parent VALUES (2); 
INSERT INTO table_child VALUES (1,1); 
INSERT INTO table_child VALUES (2,1); 
INSERT INTO table_child VALUES (3,1); 
INSERT INTO table_child VALUES (4,1); 

COMMIT; 

然後從子表中刪除1條記錄。

DELETE FROM table_child WHERE b=4; 

當我們在執行commit之前查看V $ LOCK表。 'TM'類型中有兩個'table_child'和'table_parent'的新鎖。

下面是查看V $ LOCK表的查詢。

SELECT O.OWNER, O.OBJECT_ID, O.OBJECT_NAME, O.OBJECT_TYPE, L.TYPE 
FROM DBA_OBJECTS O, V$LOCK L 
WHERE O.OBJECT_ID = L.ID1; 

問題是,爲什麼 'table_parent' 已被鎖定?

回答

3

對於維護「跨越多行」的約束(外鍵的情況),有時(即DBMS)需要序列化事務。需要序列化的時刻取決於事務對涉及表執行的更改類型的一對一。理論上(在提供快照隔離的DBMS中,這是Oracle所做的),只有當更改類型可能會違反多行約束時,DBMS是否需要自動序列化事務(例如通過獲取各種類型的鎖)。

現在在一個外鍵的情況下,需要問自己:什麼時候可以違反外鍵?有四種情況。

  • 父行被刪除:如果子行仍然存在,將違反FK。
  • 父行的鍵被更新:如果子行直到'指向'鍵的舊值,將違反FK。
  • 插入了一個子行:如果行指向了不存在的父行,將違反FK。
  • 子行的fk列值被更新:如果新列值指向不存在的父行,將違反FK。

所涉及的(2)表上的所有其他類型的交易永遠不會違反FK。所以在你的情況下,一個子行被刪除,不需要序列化。然而,Oracle可能有一些「實現特定的」原因,這迫使它獲得某種鎖定。

我已經看到了不同的方案,其中Oracle執行這種「不必要的」鎖太:你可以在這裏https://forums.oracle.com/forums/thread.jspa?messageID=10050753&#10050753

發現香椿

+0

謝謝你的回覆。你的解釋看起來非常符合邏輯。這種鎖具有名稱或術語嗎? - 順便說一句,在「鎖和外鍵」的官方文件中有非常混亂的註釋。 注意:_「子表上的DML不會獲取父表上的表鎖。」_ http://docs.oracle.com/cd/E11882_01/server.112/e16508/consist.htm#autoId24 – goldenhordes 2013-04-24 08:18:17

+0

確保正確的約束驗證(以及事務序列化)所需的鎖的學術術語是:謂詞鎖。然而,DBMS供應商並未實施謂詞鎖的概念。所以相反,他們訴諸鎖定數據對象(表和/或索引條目)。 – 2013-04-26 06:31:37

1

在table_child(a)列上添加一個索引 - 因爲這個原因,您總是索引外鍵列。