ORA-21780: 超出对象持续时间的最大数量
Posted
技术标签:
【中文标题】ORA-21780: 超出对象持续时间的最大数量【英文标题】:ORA-21780: Maximum number of object durations exceeded 【发布时间】:2019-10-31 12:40:31 【问题描述】:DATA_COUNT.REC_CNT_ACTUAL(tablename.coumnname) 中有 20 个表(table_id 从 1 到 20)需要进行计数和更新。
对于 13 个表,计数更新成功。然后弹出这个错误。
最初,我通过传递 table_id 和 table_name 将以下内容编写为过程。该过程被连续调用20次。我认为这可能是错误的原因:ORA-21780: 超出了对象持续时间的最大数量。
然后我删除了那个程序。 现在,这 20 个更新语句位于包中的 20 个不同位置。还是一样的错误。请帮助我理解问题或提出替代方案。
UPDATE DATA_COUNT
SET REC_CNT_ACTUAL=
(SELECT COUNT(1) FROM TITLE
)
WHERE TABLE_ID =20;
以下是使用的程序:
PROCEDURE DELETE_COUNT(
PI_TABLE_ID IN NUMBER,
pi_table_name IN VARCHAR2)
AS
pragma autonomous_transaction;
V_SQLERRM VARCHAR2(4000) := NULL;
V_SQLERRCODE VARCHAR2(50) := NULL;
V_CNT NUMBER;
V_SQL varchar2(4000);
BEGIN
V_SQL:='select COUNT(1) from '|| PI_TABLE_NAME;
EXECUTE immediate V_SQL INTO v_cnt;
UPDATE DATA_COUNT
SET REC_CNT_ACTUAL=v_cnt
where TABLE_ID =PI_TABLE_ID;
commit;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_sqlerrm := SUBSTR(sqlerrm,1,255);
v_sqlerrcode := SQLCODE;
/*Log error*/
datareduction_run_log (-20001, 'procedure DELETE_COUNT', CURRENT_TIMESTAMP, 'FAILED', 'Error in procedure DELETE_COUNT. Error Number:'||v_sqlerrcode||'-Error Msg:'||v_sqlerrm||'- backtrace - ' || dbms_utility.format_error_backtrace, SYSDATE, USER, NULL, NULL );
RAISE_APPLICATION_ERROR( -20001,'Unexpected Error: Error Number:'||V_SQLERRCODE||'-Error Msg:'||V_SQLERRM||'- backtrace - ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END DELETE_COUNT;
【问题讨论】:
如果正在执行的 PL/SQL 函数中存在无限递归,通常会发生这种情况。你能把完整的代码发给你吗 @Divya Sam,请你给我们看一下函数:“最初我通过传递 table_id 和 table_name 将下面的函数编写为函数。”还有你想说什么:“然后我删除了这个函数,现在这 20 条语句在包中的 20 个不同的地方”?现在有20种不同的功能?谢谢! @VBokšić 不,它们现在被编写为跨不同位置的过程的简单更新语句。所以我认为它不会同时被一次又一次地调用。所以递归错误可能会消失。但它仍然存在 所以这个选择“SELECT COUNT(1) FROM TITLE”工作正常吗?标题是表名对吗?DATA_COUNT
表上是否有 ON UPDATE
触发器?如果是这样,则可能是触发器导致了问题。
【参考方案1】:
ORA-00018:超出最大会话数
当我们没有足够的会话留给DDL/DML
操作时,我们会遇到此错误。
这是因为DDL/DML
语句需要使用递归DML
,而Oracle
中的一些递归(数据字典)操作是使用递归会话上下文完成的!
Oracle 将从会话状态对象数组 (V$SESSION / X$KSUSE) 中静默分配一个新的会话状态对象,并且所有递归操作状态对象(锁、事务状态对象等)都将属于该递归会话。
数据字典QUERIES
(填充字典缓存)也是使用单独的递归会话完成的。
没有。 session
可用和 sessions parameter
值 a 可以使用以下方法检查:
SQL> select value from v$parameter where name = 'sessions';
VALUE
--------------------------------------------------------------
170
SQL>
SQL> select count(*) from v$session;
COUNT(*)
----------
163
现在您看到,即使我们有 7
剩余会话,但我们仍然收到错误 ORA-00018
。
让我们仔细检查V$RESOURCE_LIMIT
,它向我们展示了Oracle实例中各种固定和分段数组的用法,包括会话状态对象数组V$SESSION
:
SQL> select * from v$resource_limit where resource_name = 'sessions';
RESOURCE_NAME CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_AL LIMIT_VALU
------------------------------ ------------------- --------------- ---------- ----------
sessions 170 170 170 170
您会发现CURRENT_UTILIZATION
将与会话参数值设置相同。
另外,RECURSIVE
会话用于递归数据字典调用,V$SESSION
不显示这些。
您可以通过查询表“查看此类会话”
SQL> select paddr from v$session where sid = userenv('sid');
PADDR
----------------
BF46591C
在另一个会话中,我运行了这个查询,以查看哪些会话属于上面标识的进程状态对象:
SQL> select
decode(bitand(ksuseflg,19),17,'BACKGROUND',1,'USER',2,'RECURSIVE','?'),ksuudsna
from x$ksuse s where ksusepro = 'BF46591C';
DECODE(BITAND(KSUSEFLG,19),17, KSUUDSNA
-------------------------------- ------------------------------
USER SYSTEM
RECURSIVE SYS
这两个可能也是您的情况的原因。
因此,如果您遇到 ORA-00018
错误,则将您的 sessions parameter
数组更大或配置您的应用程序以使用更少的连接或会话。
注意:您需要DBA
权限才能查询这些表。
【讨论】:
【参考方案2】:这就是我解决这个特定问题的方法:
问题是相同的过程是 UPDATING(DML) 同一个表(对象) DATA_COUNT 多次。它成功更新了26次。但之后更新(DML)开始失败。我在另一个过程中重写了一些更新。它奏效了。
【讨论】:
以上是关于ORA-21780: 超出对象持续时间的最大数量的主要内容,如果未能解决你的问题,请参考以下文章