2015-04-15 41 views
2

我們在oracle 11g數據庫遇到關於表鎖的問題。一個表可以被另一個表鎖定嗎?

我們有一個通過sql * plus執行的過程,它會截斷一個表,比如說table1。 我們有時會得到一個ORA-00054:資源繁忙,並且在表格被截斷的部分執行過程期間會收到NOWAIT錯誤。我們有一個在tomcat服務器上的webapp,當它重新啓動時(從tomcat中終止數據庫的會話),程序可以被成功執行。 table1在web應用程序的源代碼中未被使用,甚至沒有被選中,但是table1的很多父表都是。

那麼是否有可能對其父表之一的未提交更新導致鎖定?如果是這樣,我有什麼建議可以測試它? 在我們遇到問題的時候,我已經檢查過DBA,但他無法獲取阻止該過程的會話以及導致鎖定的語句。

+0

請參見: http://stackoverflow.com/questions/4842765/ora-00054-resource-busy-and-acquire-with-nowait-specified-or-timeout-expired – Syntax

回答

1

是的,父表的更新將獲得對子表的鎖定。下面是一個測試案例,證明這是可能的。

查找並追蹤特定的間歇性鎖定問題可能很痛苦。即使你無法追查具體情況,修改任何代碼以避免併發DML和DDL也是一個好主意。它不僅會導致鎖定問題,還會破壞SELECT語句。

如果卸下併發是出了問題,你可能至少要啓用DDL_LOCK_TIMEOUT使得truncate語句將等待鎖,而不是立即失敗:alter session set ddl_lock_timeout = 100000;

--Create parent/child tables, with or without an indexed foreign key. 
create table parent_table(a number primary key); 
insert into parent_table values(1); 
insert into parent_table values(2); 
create table child_table(a number references parent_table(a)); 
insert into child_table values(1); 
commit; 

--Session 1: Update parent table. 
begin 
    loop 
     update parent_table set a = 2 where a = 2; 
     commit; 
    end loop; 
end; 
/

--Session 2: Truncate child table. Eventulaly it will throw this error: 
--ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired 
begin 
    loop 
     execute immediate 'truncate table child_table'; 
    end loop; 
end; 
/
0

關於如何測試它的任何建議?

您可以檢查阻塞會話當你ORA-00054: resource busy and acquire with NOWAIT錯誤。

當一個會話在對象上保存一個排他鎖並且在另一個會話想要更新相同數據之前不釋放它時,會發生阻塞會話。這將阻止第二個,直到第一個是COMMITROLLBACK

SELECT 
    s.blocking_session, 
    s.sid, 
    s.serial#, 
    s.seconds_in_wait 
FROM 
    v$session s 
WHERE 
    blocking_session IS NOT NULL; 

例如,看到我類似的回答herehere

相關問題