Oracle 过程获取 ORA-00054:资源繁忙并使用 NOWAIT 获取

问题描述 投票:0回答:1

我有一个简单的程序。但有时会出现 ORA-00054 错误。我怀疑启用并行 DML 步骤。不过不知道有没有影响。

截断表后,我将新数据插入到截断的表中。没有其他操作来锁定该表,只有这个插入语句。

我知道截断是一个DDL操作,它是元数据的事务过程。只有一次机会锁定,截断和插入步骤必须并行启动。

有什么想法吗?

BEGIN
   -- Enable parallel DML for the session
   EXECUTE IMMEDIATE 'ALTER SESSION ENABLE PARALLEL DML';

   -- Truncate the table
   EXECUTE IMMEDIATE 'TRUNCATE TABLE my_table';

   -- Insert new data into the table with parallel DML enabled
   EXECUTE IMMEDIATE 'INSERT /*+ PARALLEL(my_table, 4) */ INTO my_table (column1, column2)
                       SELECT column1, column2 FROM another_table';

END;
oracle-database plsql oracle19c
1个回答
0
投票

尝试在您的程序中使用此代码:

BEGIN
   -- Temporary change to help debugging:
   -- Let the INSERT statement wait instead of immediately throwing the error
   -- ORA-00054: resource busy and acquire with NOWAIT
   EXECUTE IMMEDIATE 'ALTER SESSION SET ddl_lock_timeout = 1000000';

   -- Truncate the table.
   EXECUTE IMMEDIATE 'TRUNCATE TABLE my_table';

   -- Insert new data into the table with parallel DML enabled.
   EXECUTE IMMEDIATE 'INSERT /*+ ENABLE_PARALLEL_DML APPEND PARALLEL(4) */ INTO my_table (column1, column2)
                       SELECT column1, column2 FROM another_table';

   COMMIT;
END;
/

下次会话被阻塞时,它将等待而不是立即抛出错误。如果您可以在等待发生时捕获它,请使用以下查询找到阻塞会话:

-- The session that is blocking your session.
select *
from gv$session
where (inst_id, sid) in
(
    select final_blocking_instance, final_blocking_session
    from gv$session
    where final_blocking_session is not null
);

如果阻塞会话只持续很短的时间,并且您无法实时捕获它的发生,您仍然可以通过查看历史性能数据找到阻塞者。使用以下查询查找历史阻止程序,但您需要修改查询以过滤掉许多不相关的阻止程序。

GV$ACTIVE_SESSION_HISTORY
通常包含大约一天的数据。如果该数据不够旧,请将其替换为
DBA_HIST_ACTIVE_SESS_HISTORY

select *
from gv$active_session_history
where blocking_session is not null;

有很多与你相对较小的代码相关的微妙问题:

  1. 阻塞。肯定有某些东西与您的进程同时在您的桌子上工作,因此您的假设之一可能是错误的。但是,有问题的代码可能只是间接相关的 - 例如,从没有索引外键的子表中删除行的过程。
  2. 立即执行。 在示例代码中,
    EXECUTE IMMEDIATE
    不是必需的,因为您知道所有对象都是运行时的。但是,在您的过程中,您可能确实希望保留动态 SQL。您的真实代码使用一个过程,并且对被截断的表进行静态引用的过程将触发重新编译。强制自身重新编译的代码可能会导致问题,因此请保留动态 SQL。
  3. 提示。
    ENABLE_PARALLEL_DML
    可以通过提示为单个 SQL 语句启用。您可能还想将
    PARALLEL(my_table, 4)
    更改为
    PARALLEL(4)
    - 如果该语句要并行运行,您不妨并行化整个语句,而不是仅并行其一部分。
    APPEND
    提示确保语句始终以直接路径插入的方式运行。通常,并行运行 INSERT 将导致直接路径模式。但是,以防万一您的服务器暂时耗尽并行会话,您可能仍然希望获得直接路径写入,因此
    APPEND
    在某些情况下可能会有所帮助。
© www.soinside.com 2019 - 2024. All rights reserved.