Oracle Ref 分区:由于子表行迁移导致死锁

Sau*_*hin 8 oracle deadlock oracle-11g

我的订购应用程序使用 Oracle 11g 数据库。这个数据库有一个主表 ORDERS 和多个子表,如 ORDER_DETAILS、PLAN 等。

ORDERS 表在 STATUS 列上进行 LIST 分区,所有其他表都使用 ORDERID 作为外键进行引用分区。

在负载高峰时,当订单状态发生变化并且 ORDERS 表行从一个分区移动到另一个分区时,Oracle 将对 ORDERS 表分区引用的所有子表执行行迁移。由于许多表依赖于 ORDERS 表,大量行移动发生导致子表之一出现死锁。

我的问题是,如何解决在ORACLE 的内部行迁移步骤中造成的死锁?

这是一个示例设置:

订单表:

CREATE TABLE ORDERS (
       orderID   NUMBER PRIMARY KEY,
       description    VARCHAR2(30),
       status   VARCHAR2(30))
  PARTITION BY LIST (status) (  
       PARTITION A VALUES ('COMPLETED'), 
       PARTITION B VALUES ('ACTIVE'), 
       PARTITION C VALUES ('SUBMITTED'))
Run Code Online (Sandbox Code Playgroud)

子表:PLAN

CREATE TABLE PLAN (
       planID   NUMBER PRIMARY KEY,
       orderID    NUMBER,
       description   VARCHAR2(30),
       CONSTRAINT FKC64393AD1EC7235 FOREIGN KEY (orderID) 
       REFERENCES ORDERS (orderID) ON DELETE CASCADE
 )
 PARTITION BY REFERENCE (FKC64393AD1EC7235);
Run Code Online (Sandbox Code Playgroud)

还有更多子表,其中 ORDERS 是父表。

在重负载下,当 ORDER 状态改变导致行在分区之间移动时,日志中会打印以下死锁错误 ORA-00060: deadlock detected while waiting for resource

在 Oracle 跟踪日志中,我看到以下 SQL 导致死锁

update /*+ opt_param('_and_pruning_enabled', 'false') */ "TEST"."PLAN" partition (dataobj_to_partition( "TEST"."ORDERS" , :1)) move to partition (dataobj_to_partition( "TEST"."ORDERS" , :1)) set "ORDERID" = "ORDERID" where "ORDERID" = :1
Run Code Online (Sandbox Code Playgroud)

现在这个 SQL 是由 Oracle 内部生成的,用于执行子 PLAN 表的行迁移。

为了解决这个问题,我尝试了以下更改:

  1. 我已经确认 PLAN 表中的 OrderID 列(外键列)上有索引。
  2. 尝试增加表上的 PCTFREE 参数。

但是还没有成功。我如何处理这种情况下的死锁?

- - - - - - - - - - - - - 更新 - - - - - - - - - - - - ——

根据 Wernfried 和 Gandolf989 的建议,我通过运行 Gandolf989 答案中给出的查询来验证我的所有外键是否都有索引。

结果是“未找到行”。所以这意味着,所有的索引似乎都到位了。但是在分析时我意识到,如果我检查如下简单查询的解释计划,即使在 ORDERID 列上有索引后,我也会在 PLAN 表上看到完整的表扫描。

 UPDATE PLAN SET DESCRIPTION = 'ABC' WHERE orderid= '234';
Run Code Online (Sandbox Code Playgroud)

以下是最初在该表上运行的索引语句。

 CREATE INDEX IDX_PLAN_ORDERID ON  PLAN(ORDERID);
Run Code Online (Sandbox Code Playgroud)

所以出于某种原因,ORACLE 在对 PLAN 表运行更新查询时没有考虑索引。我错过了什么吗?

Gan*_*989 0

这可能是由未索引的外键引起的。Tom Kyte 有一个查询,您可以使用它来查找它们。它可以像在子表上添加一些索引一样简单。

未索引的外键