简体   繁体   English

为什么我的语句由于资源繁忙异常而失败?

[英]Why my statement failed with resource busy exception?

As a part of an ETL process,I have this exchange subpartition statement: 作为ETL流程的一部分,我有以下交换子分区语句:

ALTER TABLE DWH.QV_FACT_AMS EXCHANGE SUBPARTITION P08_2018_300_SALES WITH TABLE DWH.STG_QV_FACT_AMS;

(each run with different subpartition but the same 2 tables). (每个运行具有不同的子分区,但具有相同的2个表)。

We started to get an exception: 我们开始得到一个例外:

ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired. ORA-00054:资源正忙,并且已指定NOWAIT进行获取,或者超时已过期。

Which mean that some process update the table and we can't alter. 这意味着某些进程会更新表,而我们不能更改。

Since the final table - QV_FACT_AMS is only for reports, and the STG_QV_FACT_AMS is an inner-dynamic table that created in the ETL itself, I have no idea who can update those tables. 由于最终表-QV_FACT_AMS仅用于报告,而STG_QV_FACT_AMS是在ETL本身中创建的内部动态表,所以我不知道谁可以更新这些表。

The ETL can't collide with another run of the ETL itself, so it can't be a trying to modify the same table from those 2 processes. ETL不能与ETL本身的另一次运行发生冲突,因此它不能试图从这两个进程中修改同一张表。

The exchange statement run a lot of times per day and finished ok, and the exception raise only around 9PM. 交换声明每天运行很多次并完成正常,并且异常仅在晚上9点左右出现。

So I applied an AUDIT ALL on those 2 tables: 所以我在这两个表上应用了AUDIT ALL:

AUDIT ALL on dwh.qv_Fact_ams;
AUDIT ALL on dwh.stg_qv_Fact_ams;

But all the accesses to the tables didn't were on those hours and it was only select which doesn't supposed to lock the table. 但是所有对表的访问都不是在那几个小时内进行的,只是选择不应该锁定表。

example of the log of failure: 失败日志的示例:

LOG_ID: 5879089
START_TIME: 18-07-2019 21:29:01
END_TIME: 18-07-2019 21:29:28
STATUS: FAILED
ORA_EXCEPTION: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

we can see that the exception was in 18-07-2019 21:29:28. 我们可以看到例外发生在18-07-2019 21:29:28。

and this is the audit: 这是审计:

SELECT  * 
FROM DBA_MAINT.AUD$ 
WHERE OBJ$NAME IN ('QV_FACT_AMS','STG_QV_FACT_AMS') 
ORDER BY TIMESTAMP# DESC;

The only access except the etl itself is only action# = 3 (select), and an 3 hours later... 除了etl本身之外,唯一的访问权限只有action#= 3(选择),然后3小时后...

Set DDL_LOCK_TIMEOUT at the session level to find out who is blocking the command. 在会话级别上设置DDL_LOCK_TIMEOUT以找出谁阻止了该命令。

With the default settings, DDL on a locked table will immediately fail: 使用默认设置,锁定表上的DDL将立即失败:

--Session #1: Insert but do not commit:
create table table1(a number);
insert into table1 values(1);

--Session #2:
--ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
alter table table1 move;

Instead, we can tell Oracle to wait for a certain number of seconds instead of failing immediately. 相反,我们可以告诉Oracle等待一定的秒数,而不是立即失败。

--Session #2:
--The second command will hang for 9999 seconds, or until the lock is free.
alter session set ddl_lock_timeout = 9999;
alter table table1 move;

That gives us enough time to investigate what session and statement are blocking our commands. 这给了我们足够的时间来调查哪些会话和语句阻塞了我们的命令。 There are many ways to find blockers, and there may be many false positives. 查找阻止程序的方法有很多,并且可能有很多误报。 This code is a good starting point: 这段代码是一个很好的起点:

--Find potential blockers:
select sid, final_blocking_session, gv$session.*
from gv$session
where final_blocking_session is not null;

Once we have the FINAL_BLOCKING_SESSION (which is the SID for the blocking session), we can find out more information about that session, like what statement it's running. 一旦有了FINAL_BLOCKING_SESSION(这是阻塞会话的SID),我们就可以找到有关该会话的更多信息,例如它正在运行的语句。 This SQL statement can help investigate the blocker: 此SQL语句可以帮助调查阻止程序:

--Use the FINAL_BLOCKING_SESSION from above.
select *
from gv$sql
join gv$session
    on gv$sql.sql_id = gv$session.sql_id
where sid = <final_blocking_session>;

Hopefully some of that information will make sense and reveal the culprit. 希望其中的一些信息有意义并揭示了罪魁祸首。 Since the change didn't show up in the audit trail, I'm guessing there's a SYS user running a command, since SYS is not audited in the same place. 由于更改没有显示在审计跟踪中,因此我猜有一个SYS用户在运行命令,因为SYS不在同一位置进行审计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ORA-00054: 资源繁忙并获取指定的 NOWAIT 或超时过期,异常是 java.sql.SQLException - ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired, exception is java.sql.SQLException 重建索引时资源繁忙 - resource busy while rebuilding an index 我的SqlDataSource中的WHERE语句导致无效字符异常(ORA-00911),为什么? - A WHERE statement in my SqlDataSource causes invalid character exception (ORA-00911), why? ARJUNA017017:使用 Oracle 但不使用 MySQL 登记资源失败异常 - ARJUNA017017: enlist of resource failed exception with Oracle but not with MySQL 为什么没有提出我的例外? - Why is my exception not being raised? 为什么语句在Toad中执行而在我的代码中不执行? - Why would a statement execute in Toad but not in my code? 为什么我的更新语句没有更新表? - Why is my update statement not updating the table? 为什么我的 null 检查在 Oracle 的这个 IF 语句中不起作用? - Why is my null check not working in this IF statement in Oracle? ORA-00054:资源繁忙并在Oracle过程中使用NOWAIT进行获取 - ORA-00054: resource busy and acquire with NOWAIT in oracle procedure ORA-00054: 资源繁忙并使用指定的 NOWAIT 获取或超时已过期 - ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM