1

有 20 个表(table_id 从 1 到 20)需要在 DATA_COUNT.REC_CNT_ACTUAL(tablename.coumnname) 中获取和更新其计数。

对于 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;

4

2 回答 2

2

ORA-00018: 超出最大会话数

当我们没有足够的会话留给我们的DDL/DML操作时,我们会得到这个错误。

这是因为DDL/DML语句需要使用递归DML,并且某些递归(数据字典)操作Oracle是使用递归会话上下文完成的!

Oracle 将从会话状态对象数组 (V$SESSION / X$KSUSE) 中静默分配一个新的会话状态对象,并且所有递归操作状态对象(锁、事务状态对象等)都将属于该递归会话。数据字典QUERIES(填充字典缓存)也是使用单独的递归会话完成的。

可用数量sessionsessions 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会话参数值设置将相同。

session也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权限才能查询这些表。

于 2019-11-03T11:44:04.300 回答
0

这就是我解决这个特定问题的方法:

问题是相同的过程是多次更新(DML)同一个表(对象)DATA_COUNT。它成功更新了26次。但之后更新(DML)开始失败。我在另一个过程中重写了一些更新。它奏效了。

于 2019-11-05T13:27:33.717 回答