2

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

我们有一个通过 sql*plus 执行的过程,它截断一个表,比如说 table1。我们有时会收到 ORA-00054: resource busy and acquire with NOWAIT error during the procedure at the part of the part of the table is to be truncated. 我们有时会收到 ORA-00054: resource busy and acquire with NOWAIT error during the procedure at the part of the part of the table is to betruncated. 我们有一个位于 tomcat 服务器中的 webapp,当重新启动时(从 tomcat 终止与数据库的会话),该过程可以重新成功执行。在webapp的源代码中没有使用table1,甚至在select中也没有使用,但是table1的很多父表都是。

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

4

2 回答 2

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;
/
于 2015-04-15T06:02:47.283 回答
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;

例如,在此处此处查看我的类似答案。

于 2015-04-15T05:20:35.870 回答