表可以被另一个表锁定吗?

时间:2015-04-15 03:10:02

标签: oracle locking ora-00054

我们在oracle 11g数据库上遇到有关表锁的问题。

我们有一个通过sql * plus执行的过程,它会截断一个表,比如说table1。 我们有时会得到一个ORA-00054:资源忙,并且在要截断表时在部件执行过程期间获取NOWAIT错误。我们有一个位于tomcat服务器中的webapp,当重新启动时(为了从tomcat中杀死数据库的会话),该过程可以成功重新执行。 table1在webapp的源代码中没有被使用,甚至没有在select中使用,但是table1的很多父表都是。

因此,对其父表之一的未提交更新是否可能导致锁定?如果是的话,有关我如何测试的任何建议吗? 在我们遇到问题的时候,我已经与DBA核实了,但他无法获得阻止程序和导致锁定的语句的会话。

2 个答案:

答案 0 :(得分: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;
/

答案 1 :(得分:0)

  

关于我如何测试它的任何建议?

如果出现ORA-00054: resource busy and acquire with NOWAIT错误,您可以查看阻止会话

当一个会话在对象上持有独占锁并且在另一个会话想要更新相同数据之前不释放它时,会发生阻止会话。这将阻止第二个,直到第一个是 COMMIT ROLLBACK

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

例如,请参阅我的类似答案herehere