簡體   English   中英

Oracle鎖定問題-ORA-00054:創建外鍵時資源繁忙

[英]Oracle lock issue - ORA-00054: resource busy - while creating a foreign key

初始情況:

  • 表PARENT_TABLE在其列PK_COL上具有主鍵。
  • 表CHILD_TABLE1在PARENT_TABLE(PK_COL)上具有外鍵。

我在事務中向CHILD_TABLE1中插入一行,並且不提交。

然后,我嘗試在另一個會話中創建與CHILD_TABLE1對稱的表CHILD_TABLE2。 但是,由於正在CHILD_TABLE1中不斷進行插入,因此在創建外鍵時會引發ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

我不明白為什么Oracle阻止外鍵創建:在PARENT_TABLE上沒有執行任何修改。

請幫忙。

要在sqlplus下重現:

set autocommit off

create table PARENT_TABLE(PK_COL varchar(10));
alter table PARENT_TABLE add constraint PK_CONSTRAINT primary key (PK_COL);
insert into PARENT_TABLE values ('foo');
commit;

create table CHILD_TABLE1(CHILD_PK_COL varchar(10), FK_COL varchar(10));
alter table CHILD_TABLE1 add constraint CHILD_TABLE1_CONSTRAINT foreign key (FK_COL) references PARENT_TABLE(PK_COL);
create index CHILD_TABLE1_INDEX on CHILD_TABLE1(FK_COL);
insert into CHILD_TABLE1 values ('bar', 'foo');

在另一個控制台中:

alter session set ddl_lock_timeout=10;
create table CHILD_TABLE2(CHILD_PK_COL varchar(10), FK_COL varchar(10));
alter table CHILD_TABLE2 add constraint CHILD_TABLE2_CONSTRAINT foreign key (FK_COL) references PARENT_TABLE(PK_COL);

有趣的是:在創建CHILD_TABLE2_CONSTRAINT中使用NOVALIDATE時,執行被掛起...

您沒有在父表中進行任何修改。 但是實際上,您是在嘗試在子表中引用其主鍵。 在與表建立關系或任何DDL之前,它必須沒有鎖。

因此,在創建此約束之前,Oracle會檢查所引用表( PARENT_TABLE )上的現有鎖。 鎖定表(在此上下文中為表級別鎖定)實際上是出於遵守ACID屬性的原因。

理解其重要性的一個最佳示例是ON DELETE CASCADE ,這意味着如果父表中的記錄被刪除,則子表中的對應記錄將被自動刪除。

因此,當子表引用父表時存在未提交的插入/更新/刪除操作時。 不能為父級創建其他引用約束。 只是為了避免出現僵局或混亂。

為了更加清晰,當子表中有未提交的插入內容時。 父表上也有一個鎖。 因此,所有其他引用它的DDL將被等待。

您可以使用此查詢進行檢查。

SELECT c.owner,
  c.object_name,
  c.object_type,
  b.sid,
  b.serial#,
  b.status,
  b.osuser,
  b.machine
FROM v$locked_object a ,
  v$session b,
  dba_objects c
WHERE b.sid     = a.session_id
AND a.object_id = c.object_id;

我在查詢中添加了LOCKED_MODE解釋:

DECODE(a.LOCKED_MODE, 0,'NONE', 1,'NULL', 2,'ROW SHARE (RS/SS)', 3,'ROW EXCLUSIVE (RX/SX)', 4,'SHARE (S)', 5,'SHARE ROW EXCLUSIVE (SRX/SSX)', 6,'EXCLUSIVE (X)', NULL) LOCK_MODE.

結果如下:

OBJECT_NAME                    OBJECT_TYPE         LOCK_MODE                         SID    SERIAL# STATUS
------------------------------ ------------------- ----------------------------- ---------- ---------- --------
PARENT_TABLE                   TABLE               ROW EXCLUSIVE (RX/SX)              71          8694 INACTIVE
CHILD_TABLE1                   TABLE               ROW EXCLUSIVE (RX/SX)              71          8694 INACTIVE

RX / SX是一個表鎖,因此它可以防止任何DDL操作(這在文檔中似乎有說)。 父母和孩子都使用此鎖。 我想鎖是在父級上添加的,至少可以防止它被刪除,因此我們將丟失子表上的掛起更新。

也就是說,我仍然沒有解決方案。 假設父表是制造商 有一個兒童汽車桌,我們正在向該表中插入大量新車。 汽車制造商都有一把外鍵。 現在,我們要管理一個新產品:“自行車”。 因此,我們想創建一個類似於car自行車桌。 但是,由於要在car中執行插入操作,因此無法創建表。 似乎是一個非常簡單的用例...如何支持它?

=====編輯:可能沒有解決方案。 這是一個有同樣問題的人

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM