ORA-21780: превышено максимальное количество длительностей объекта - PullRequest
1 голос
/ 31 октября 2019

Существует 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;

Ответы [ 2 ]

2 голосов
/ 03 ноября 2019

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.

0 голосов
/ 05 ноября 2019

Вот как я решил эту конкретную проблему:

Проще говоря, проблема заключалась в том, что процедура (скажем, method_H) ОБНОВЛЯЛА (DML) одну и ту же таблицу (объект) DATA_COUNT несколько раз. Первоначально я вызывал процедуру DELETE_COUNT внутри method_H, который уже несколько раз обновлял таблицу DATA_COUNT. Моя процедура DELETE_COUNT обновит ту же таблицу DATA_COUNT еще пару раз. Итак, ошибка произошла. Я решил это, вызвав мою процедуру DELETE_COUNT внутри последней процедуры (скажем, method_Z) процесса.

Подробно:

В той же самой процедуре (процедуре_H) таблица DATA_COUNT была ОБНОВЛЕНА (DML) несколько раз и для различных других целей (здесь уже 19 обновлений)).

Я вызывал процедуру DELETE_COUNT внутри той же самой процедуры (method_H), которая снова ОБНОВЛЯЕТ таблицу DATA_COUNT. (Еще 19 раз).

Итак, в общей сложности одна и та же процедура пыталась обновить таблицу DATA_COUNT 38 раз. Это не удалось после 26 ОБНОВЛЕНИЙ, чтобы быть точным.

Таким образом, вместо вызова процедуры DELETE_COUNT в процедуре_H, я вызвал ее в последней процедуре, которая в итоге создает отчет csv (Процедура_Z). Процедура_Z ОБНОВИТ таблицу DATA_COUNT в общей сложности 19 раз. Таким образом, объект DATA_COUNT не получает UDPATED (DML) слишком много раз внутри одной и той же процедуры!

...