Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 为什么我的语句因资源繁忙异常而失败?_Oracle_Etl_Audit_Table Locking - Fatal编程技术网

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

Oracle 为什么我的语句因资源繁忙异常而失败?,oracle,etl,audit,table-locking,Oracle,Etl,Audit,Table Locking,作为ETL流程的一部分,我有以下exchange子分区声明: ALTER TABLE DWH.QV_FACT_AMS EXCHANGE SUBPARTITION P08_2018_300_SALES WITH TABLE DWH.STG_QV_FACT_AMS; 每个运行都有不同的子分区,但有相同的2个表 我们开始遇到一个异常: ORA-00054:资源繁忙,并在指定NOWAIT或超时的情况下获取 过期了 这意味着某些进程会更新表,而我们无法更改 由于最终的表-QV_FACT_AMS仅用于报告

作为ETL流程的一部分,我有以下exchange子分区声明:

ALTER TABLE DWH.QV_FACT_AMS EXCHANGE SUBPARTITION P08_2018_300_SALES WITH TABLE DWH.STG_QV_FACT_AMS;
每个运行都有不同的子分区,但有相同的2个表

我们开始遇到一个异常:

ORA-00054:资源繁忙,并在指定NOWAIT或超时的情况下获取 过期了

这意味着某些进程会更新表,而我们无法更改

由于最终的表-QV_FACT_AMS仅用于报告,而STG_QV_FACT_AMS是在ETL本身中创建的一个内部动态表,因此我不知道谁可以更新这些表

ETL不会与ETL本身的另一次运行发生冲突,因此它不会试图从这两个进程中修改同一个表

exchange语句每天运行很多次,结果正常,异常仅在晚上9点左右出现

所以我对这两个表都进行了审核:

AUDIT ALL on dwh.qv_Fact_ams;
AUDIT ALL on dwh.stg_qv_Fact_ams;
但是,对表的所有访问都不是在这些时间进行的,只有select不应该锁定表

故障日志的示例:

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
我们可以看到,例外发生在2019年7月18日21:29:28

这就是审计:

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

除etl本身外,唯一的访问是仅操作=3选择,3小时后…

在会话级别设置DDL\u锁定\u超时,以查明谁在阻止该命令

使用默认设置,锁定表上的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;
相反,我们可以告诉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;
这给了我们足够的时间来调查是什么会话和语句阻塞了我们的命令。有很多方法可以找到阻滞剂,并且可能有很多误报。这段代码是一个很好的起点:

--Find potential blockers:
select sid, final_blocking_session, gv$session.*
from gv$session
where final_blocking_session is not null;
一旦我们有了最后一个_BLOCKING_会话,它是阻塞会话的SID,我们就可以找到关于该会话的更多信息,比如它正在运行的语句。此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>;

希望这些信息中的一些会有意义,并揭示出罪犯。由于更改未显示在审核跟踪中,我猜是SYS用户在运行命令,因为SYS未在同一位置进行审核。

在会话级别设置DDL_LOCK_TIMEOUT,以找出谁在阻止该命令

使用默认设置,锁定表上的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;
相反,我们可以告诉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;
这给了我们足够的时间来调查是什么会话和语句阻塞了我们的命令。有很多方法可以找到阻滞剂,并且可能有很多误报。这段代码是一个很好的起点:

--Find potential blockers:
select sid, final_blocking_session, gv$session.*
from gv$session
where final_blocking_session is not null;
一旦我们有了最后一个_BLOCKING_会话,它是阻塞会话的SID,我们就可以找到关于该会话的更多信息,比如它正在运行的语句。此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>;

希望这些信息中的一些会有意义,并揭示出罪犯。由于更改没有显示在审核跟踪中,我猜是SYS用户在运行命令,因为SYS未在同一位置进行审核。

是否可能重复?您发送的问题与此异常的原因有关。。我知道有东西把桌子锁上了。我只是找不到锁定会话。是否可能重复?如何重复?您发送的问题与此异常的原因有关。。我知道有东西把桌子锁上了。我就是找不到锁定会话。