![](/img/trans.png)
[英]ORA-00054: resource busy and acquire with NOWAIT in oracle procedure
[英]Oracle lock issue - ORA-00054: resource busy - while creating a foreign key
初始情況:
我在事務中向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.