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: 超出对象持续时间的最大数量的主要内容,如果未能解决你的问题,请参考以下文章

如何避免“超出 GET/POST 参数数量”错误?

ReactJS - 超出最大更新深度错误

移动云消息队列RabbitMQ对资源创建数量有限制吗?

已超出最大可命名字符数配额 (16384)

RecursionError:重命名列条目后调用 Python 对象时超出最大递归深度

Python:调用 Python 对象时超出了最大递归深度