Oracle - 从子表中删除行会锁定父表

时间:2013-04-24 02:24:56

标签: oracle locking foreign-keys deadlock

我们在Oracle 11.2g中遇到了死锁问题。发生死锁的一个潜在原因是从子表锁父表中删除。我从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;

当我们在执行提交之前查看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 个答案:

答案 0 :(得分:3)

对于维护“跨越多行”的约束(外键的情况),有时(即DBMS)需要序列化事务。需要序列化的时刻取决于事务在涉及的表上执行的更改类型的一对一。理论上(在提供快照隔离的DBMS中,这就是Oracle所做的),只有当变更类型可能违反多行约束时,DBMS才需要自动序列化事务(例如通过获取各种事务)锁类型)。

现在在外键的情况下,需要问自己:何时可以侵犯外键?有四种情况。

  • 删除父行:如果子行仍然存在,则会违反FK。
  • 父行的密钥更新:如果子行直到'指向'旧密钥值,将违反FK。
  • 插入子行:如果行指向不存在的父行,则会违反FK。
  • 子行的fk-column值已更新:如果新列值指向不存在的父行,则将违反FK。

所涉及的(2)表上的所有其他类型的交易都不会违反FK。因此,在您的情况下,删除子行,不需要序列化。然而,Oracle可能有一些“特定于实现”的原因,这迫使它获得某种锁定。

我已经看到了Oracle执行此类“不必要”锁定的不同情况:您可以在此处找到https://forums.oracle.com/forums/thread.jspa?messageID=10050753&#10050753

香椿

答案 1 :(得分:1)

在table_child(a)列上添加一个索引 - 出于这个原因,你总是索引外键列。

答案 2 :(得分:0)