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

Can a table be locked by another table?

我们在 oracle 11g 数据库上遇到了关于 table 锁的问题。

我们有一个通过 sql*plus 执行的过程,它截断了 table,比方说 table1。 在要截断 table 的过程中,我们有时会遇到 ORA-00054: resource busy and acquire with NOWAIT 错误。我们有一个位于 tomcat 服务器中的 Web 应用程序,当它重新启动时(终止从 tomcat 到数据库的会话),该过程可以重新成功执行。 table1 没有使用,甚至在 select 中也没有使用,在 webapp 的源代码中,但是 table1 的很多父 table 是。

那么是否有可能是对其父 table 之一的未提交更新导致了锁定?如果是这样,关于我如何测试它有什么建议吗? 遇到问题时,我曾与 DBA 核实过,但他无法获取阻塞过程的会话和导致锁定的语句。

any suggestions on how I can test it?

当您遇到 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;

例如看我类似的回答here and here

是的,父 table 的更新将锁定子 table。下面是一个证明它是可能的测试用例。

查找和跟踪特定的间歇性锁定问题可能很痛苦。即使您无法追查具体情况,修改任何代码以避免并发 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;
/