4

我们在 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'被锁定了?

4

3 回答 3

3

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

现在在外键的情况下,需要问自己:什么时候可以违反外键?有四种情况。

  • 删除父行:如果子行仍然存在,将违反 FK。
  • 父行的键被更新:如果子行直到“指向”键的旧值,将违反 FK。
  • 插入子行:如果行指向不存在的父行,将违反 FK。
  • 更新子行的 fk-column 值:如果新列值指向不存在的父行,将违反 FK。

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

我也见过 Oracle 执行这种“不必要”锁定的不同场景:您可以在这里找到它https://forums.oracle.com/forums/thread.jspa?messageID=10050753峁

香椿

于 2013-04-24T06:59:26.297 回答
1

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

于 2013-04-24T06:50:47.367 回答
0

此处通过示例解释了此问题的答案http://www.oraclebin.com/2012/12/what-is-deadlock-in-oracle.html

于 2013-12-27T11:02:40.523 回答