Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / как перехватить все исключения? / 25 сообщений из 30, страница 1 из 2
20.04.2021, 16:07
    #40064206
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
напоролся на Ora-01013 на пром стенде. до этого не знал о существовании exceptions, которые не перехватываются блоком when others. очень не хочется повторения сюрприза.
собственно вопрос: есть ли еще какие нибудь исключений, требующие отдельного ухода?
мб кто-нибудь поделится -как правильно писать обработку исключений с учетом таких вот особенностей.
...
Рейтинг: 0 / 0
20.04.2021, 16:24
    #40064210
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg
есть ли еще какие нибудь исключений, требующие отдельного ухода?

Конечно есть. Помимо исключений, связанных с логином или с потерей соединения к подобным относятся "обертки" над аварийным завершением серверного процесса (например, ORA-600, ORA-7445)
...
Рейтинг: 0 / 0
20.04.2021, 17:04
    #40064228
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
andrey_anonymous
legg
есть ли еще какие нибудь исключений, требующие отдельного ухода?

Конечно есть. Помимо исключений, связанных с логином или с потерей соединения к подобным относятся "обертки" над аварийным завершением серверного процесса (например, ORA-600, ORA-7445)

если сессия отваливается - то вопрос сам снимается. проблема как раз когда сессия вошла в процедуру, наапдейтила -навыставляла юзерлоки и вылетела по 01013. И после этого занялась другими делами спокойно.
...
Рейтинг: 0 / 0
20.04.2021, 17:06
    #40064230
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg
andrey_anonymous
пропущено...

Конечно есть. Помимо исключений, связанных с логином или с потерей соединения к подобным относятся "обертки" над аварийным завершением серверного процесса (например, ORA-600, ORA-7445)

если сессия отваливается - то вопрос сам снимается. проблема как раз когда сессия вошла в процедуру, наапдейтила -навыставляла юзерлоки и вылетела по 01013. И после этого занялась другими делами спокойно.

получается что незавершенная транзакция так и зависает в раскуроченном состоянии на веки вечные (пока сессия не закончится по каким то другим причинам).
...
Рейтинг: 0 / 0
20.04.2021, 19:02
    #40064269
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
[quot legg#22311566]
legg

получается что незавершенная транзакция так и зависает в раскуроченном состоянии на веки вечные (пока сессия не закончится по каким то другим причинам).


А чем это отличается от вызова процедуры в которой вообще нет блока exception? Вернее, процедура в которой есть блок exception в 95% случаев это плохой дизайн. Обработка исключения это дело клиента. То же исключение в той же процедуре но вызванной из другой части приложения во многих случаях вызывает разную реакцию. Далее, любой код приложения без try catch рано или поздно выстрелит.

SY.
...
Рейтинг: 0 / 0
20.04.2021, 19:09
    #40064273
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
SY
Вернее, процедура в которой есть блок exception в 95% случаев это плохой дизайн.
Соломон, не лезь в девелоперские дебри. Ты сейчас однозначно не в теме. Оставайся дба-шником.
...
Рейтинг: 0 / 0
20.04.2021, 20:10
    #40064290
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
SY
А чем это отличается от вызова процедуры в которой вообще нет блока exception?

именно так. ничем в данном случае.
SY
Вернее, процедура в которой есть блок exception в 95% случаев это плохой дизайн. Обработка исключения это дело клиента.

так изначально и задумывалось в проекте, насколько знаю (те, кто начинал эту историю - свалили). и я неоднократно слышал что клиент должен исключения обрабатывать. но
1. я не хочу показаться упертым бараном, но буду! или я не просто не могу переломить мозг в правильном направлении или в данном случае - исключение
2. подробнее: по бизнес логике процедура должна работать со счетом в монопольном режиме. для этого выставляется юзер лок по счету (наименование ul содержит id счета). Если счет уже заблокирован - ждем пока юзер блок не будет снят. После того как процедура отработана - блокировку снимаем. В блоке EXCEPTION WHEN OTHERS также снимаем блокировку а EXCEPTION или превращаем в ответ пользователю или рейзим. Такой способ блокировки написал не я но не вижу в нем ничего плохого.
Не видел до тех пор пока не обнаружилось что часть вызовов прерывается пользователем, сессия начинает выполнять другие задачи, а блокировка так и остается висеть.
Неужели обязанность проверить блокировку счета и снять ее при ее наличии в данном случае правильнее возложить на клиента? Ему чисто технически это сложнее сделать, тем более что он инициирует не один вызов процедуры а целый цикл (входной параметр - массив документов).
...
Рейтинг: 0 / 0
20.04.2021, 20:22
    #40064294
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg
SY
А чем это отличается от вызова процедуры в которой вообще нет блока exception?

именно так. ничем в данном случае.
SY
Вернее, процедура в которой есть блок exception в 95% случаев это плохой дизайн. Обработка исключения это дело клиента.

так изначально и задумывалось в проекте, насколько знаю (те, кто начинал эту историю - свалили). и я неоднократно слышал что клиент должен исключения обрабатывать. но
1. я не хочу показаться упертым бараном, но буду! или я не просто не могу переломить мозг в правильном направлении или в данном случае - исключение
2. подробнее: по бизнес логике процедура должна работать со счетом в монопольном режиме. для этого выставляется юзер лок по счету (наименование ul содержит id счета). Если счет уже заблокирован - ждем пока юзер блок не будет снят. После того как процедура отработана - блокировку снимаем. В блоке EXCEPTION WHEN OTHERS также снимаем блокировку а EXCEPTION или превращаем в ответ пользователю или рейзим. Такой способ блокировки написал не я но не вижу в нем ничего плохого.
Не видел до тех пор пока не обнаружилось что часть вызовов прерывается пользователем, сессия начинает выполнять другие задачи, а блокировка так и остается висеть.
Неужели обязанность проверить блокировку счета и снять ее при ее наличии в данном случае правильнее возложить на клиента? Ему чисто технически это сложнее сделать, тем более что он инициирует не один вызов процедуры а целый цикл (входной параметр - массив документов).


да по сути не важно где этот самый блок exception. Тема интересная, но не о том. Клиент ровно так же должен будет выловить и обработать исключение. вопрос - как сделать это надежно на 100%? WHEN OTHERS не хватает. Как минимум надо проверить 01013 персонально. А есть еще что-то подобное? Смерть сессии не считается. Нет сессии - незафиксированные транзакции и блокировки самоликвидируются.
...
Рейтинг: 0 / 0
20.04.2021, 21:24
    #40064299
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg

да по сути не важно где этот самый блок exception. Тема интересная, но не о том. Клиент ровно так же должен будет выловить и обработать исключение. вопрос - как сделать это надежно на 100%? WHEN OTHERS не хватает. Как минимум надо проверить 01013 персонально. А есть еще что-то подобное? Смерть сессии не считается. Нет сессии - незафиксированные транзакции и блокировки самоликвидируются.


Try catch или аналог для используемого клиента.

SY.
...
Рейтинг: 0 / 0
20.04.2021, 22:44
    #40064311
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
SY
legg

да по сути не важно где этот самый блок exception. Тема интересная, но не о том. Клиент ровно так же должен будет выловить и обработать исключение. вопрос - как сделать это надежно на 100%? WHEN OTHERS не хватает. Как минимум надо проверить 01013 персонально. А есть еще что-то подобное? Смерть сессии не считается. Нет сессии - незафиксированные транзакции и блокировки самоликвидируются.


Try catch или аналог для используемого клиента.

SY.

а дальше? вызов процедуры аварийного завершения, которая будет проверять, какие блокировки выставлены исходной процедурой и снимать их? мб это по феншую, но я пока не дорос до его осознания. на уровне процедуры перехватить - проще и быстрее и понятнее же. чем больше думаю - тем больше смысла вижу в таком дизайне. однако поздно. там есть еще препятствия. Вы совсем меня заплюете - но коммиты-роллбеки я волевым решением тоже у клиента отобрал, иначе очень сильно логика усложнялась:). Но это уже оверофтоп.
а еще - это передача проблемы в другую команду разработчиков. не хочу и не буду).
если дойдет дело до рефакторинга - я еще раз как следует подумаю , но сейчас таки и а все-таки:
как гарантированно перехватить все исключения (при которых сессия не умирает) в блоке EXCEPTION или такая информация просто отсутствует?
...
Рейтинг: 0 / 0
21.04.2021, 00:07
    #40064318
AlexFF__|
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg

как гарантированно перехватить все исключения (при которых сессия не умирает) в блоке EXCEPTION или такая информация просто отсутствует?

Никак.
Чтобы сделать что-нибудь нужно иметь управление, а если клиент завершает CALL, например по Ora-01013, исполнение текущего кода прерывается.
При этом сама сессия может оставаться в добром здравии и готова к дальнейшим действиям.
...
Рейтинг: 0 / 0
21.04.2021, 00:34
    #40064319
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
AlexFF__|
legg

как гарантированно перехватить все исключения (при которых сессия не умирает) в блоке EXCEPTION или такая информация просто отсутствует?

Никак.
Чтобы сделать что-нибудь нужно иметь управление, а если клиент завершает CALL, например по Ora-01013, исполнение текущего кода прерывается.
При этом сама сессия может оставаться в добром здравии и готова к дальнейшим действиям.

не совсем так.
исключение перехватывается при проверке его персонально:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
DECLARE
   e_1013 EXCEPTION;
   PRAGMA EXCEPTION_INIT(e_1013, -1013);
BEGIN
    BEGIN
          RAISE e_1013;
    EXCEPTION WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE('сюда не попадем');
    END;

EXCEPTION WHEN e_1013 THEN
    DBMS_OUTPUT.PUT_LINE('но попадем сюда');
END;
/



в итоге не придумал ничего лучше, чем в процедурах с выставлеными юзерлоками писать
Код: plsql
1.
2.
3.
4.
5.
EXCEPTION WHEN e_1013 THEN
     dbms_lock.release ...
                 WHEN OTHERS THEN
     dbms_lock.release ...
END;


и озадачен вопросом - а нет ли еще какого исключения, со свойствами 1013?
...
Рейтинг: 0 / 0
21.04.2021, 09:23
    #40064352
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg

не совсем так.
исключение перехватывается при проверке его персонально:

интересно отработает ли Ваш код если user requested cancel of current на клиенте, напр от ODBC

.....
stax
...
Рейтинг: 0 / 0
21.04.2021, 09:27
    #40064354
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
.
...
Рейтинг: 0 / 0
21.04.2021, 09:31
    #40064355
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg,

Есть мнение, что если процедура что-то делает и в случае успеха выполняет коммит, то процедуру стоит оформить в виде автономной транзакции.
Конкретно с Ora-01013 не проверял, но, т.к. автономная транзакция должна выполнять rollback в случае необработанных ошибок, думается это может сработать (и блокировки должны сняться сами при выходе из процедуры как при завершении сессии).
...
Рейтинг: 0 / 0
21.04.2021, 10:20
    #40064368
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
delphinotes
legg,

Есть мнение, что если процедура что-то делает и в случае успеха выполняет коммит, то процедуру стоит оформить в виде автономной транзакции.
Конкретно с Ora-01013 не проверял, но, т.к. автономная транзакция должна выполнять rollback в случае необработанных ошибок, думается это может сработать (и блокировки должны сняться сами при выходе из процедуры как при завершении сессии).

нет. не снимается, хоть от ролбэчься
пруф:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
declare
   res number;
   hndl varchar2(2000);
begin
   dbms_lock.allocate_unique('dolbannaya_user_lock',
                             lockhandle      => hndl);
   --dbms_output.put_line(hndl);                            
   res := dbms_lock.request(hndl,
                            dbms_lock.x_mode,
                            timeout => 0);
   rollback;
   ROLLBACK;
   RoLlBaCk;
exception when others then
   rollback;                           
end;


и пока не убоем сессию - лок висит
select * from sys.dbms_lock_allocated nm, v$lock lck where nm.name ='dolbannaya_user_lock' and nm.lockid=lck.id1;
...
Рейтинг: 0 / 0
21.04.2021, 10:29
    #40064376
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg,

это не автономная транзакция.
Оформи свою процедуру с прагмой:
Код: plsql
1.
pragma autonomous_transaction;


(либо оберни вызов своей процедуры в другую с этой прагмой и дёргай из клиента обёртку)
...
Рейтинг: 0 / 0
21.04.2021, 10:45
    #40064382
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
delphinotes
legg,

это не автономная транзакция.
Оформи свою процедуру с прагмой:
Код: plsql
1.
pragma autonomous_transaction;



(либо оберни вызов своей процедуры в другую с этой прагмой и дёргай из клиента обёртку)

я не вижу разницы в данном случае) но ок:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
declare
   res number;
   hndl varchar2(2000);
   pragma autonomous_transaction;
begin
   dbms_lock.allocate_unique('dolbannaya_user_lock',
                             lockhandle      => hndl);
   --dbms_output.put_line(hndl);                            
   res := dbms_lock.request(hndl,
                            dbms_lock.x_mode,
                            timeout => 0);
   rollback;
   ROLLBACK;
   RoLlBaCk;
exception when others then
   rollback;                           
end;


и в другой сессии
Код: plsql
1.
select * from sys.dbms_lock_allocated nm, v$lock lck where nm.name ='dolbannaya_user_lock' and nm.lockid=lck.id1;


замечательно возвращает результат
...
Рейтинг: 0 / 0
21.04.2021, 11:00
    #40064391
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg,

а вызвать dbms_lock.request с параметром release_on_commit => true религия не позволяет?
...
Рейтинг: 0 / 0
21.04.2021, 11:11
    #40064393
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
я то вот о чём, при оформлении процедуры как автономная транзакция, rollback можно явно не писать, и ecxeption блок можно тоже опустить (если конечно не нужно это записать в протокол), т.е. твоё пример может выглядеть так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
declare
  pragma autonomous_transaction;
  l_lock_handle varchar2(128);
  l_lock_result integer;
begin
  dbms_lock.allocate_unique('dolbannaya_user_lock', l_lock_handle);
  l_lock_result := dbms_lock.request(l_lock_handle, dbms_lock.x_mode, 0, release_on_commit => true);
  if l_lock_result in (0, 4) then
    -- симуляция долгой работы:
    for i in 1 .. 10 loop
      dbms_lock.sleep(1);
    end loop;
  end if;
  commit;
end;
/



и пока оно работает - блокировка висит. Если прервать по OCI_BREAK, то хоть явного rollback и нету, но блокировка уйдёт, т.к. rollback будет не явный
...
Рейтинг: 0 / 0
21.04.2021, 11:12
    #40064394
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
Stax
legg

не совсем так.
исключение перехватывается при проверке его персонально:

интересно отработает ли Ваш код если user requested cancel of current на клиенте, напр от ODBC

.....
stax

отрабатывает. я проверил. работает как в pl/sql developer:
попробуйте щелкнуть молнию break
с закомментареным блоком EXCEPTION и раскомментаренным:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
declare
e_tst exception;
pragma exception_init(e_tst,-01013);
begin
  --dbms_output.put_line(sqlerrm(-10237));
  for ii in 1 .. 100 loop
    dbms_lock.sleep(5);
  end loop;
--exception when e_tst then null;
end;   



на боевом клиенте тоже проверил (клиент работает с оракловым universal connection pull ) - в логах увидел что процедура исключение перехватывать начала, т.о. минимальное решение найдено.
...
Рейтинг: 0 / 0
21.04.2021, 11:20
    #40064397
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
delphinotes
я то вот о чём, при оформлении процедуры как автономная транзакция, rollback можно явно не писать, и ecxeption блок можно тоже опустить (если конечно не нужно это записать в протокол), т.е. твоё пример может выглядеть так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
declare
  pragma autonomous_transaction;
  l_lock_handle varchar2(128);
  l_lock_result integer;
begin
  dbms_lock.allocate_unique('dolbannaya_user_lock', l_lock_handle);
  l_lock_result := dbms_lock.request(l_lock_handle, dbms_lock.x_mode, 0, release_on_commit => true);
  if l_lock_result in (0, 4) then
    -- симуляция долгой работы:
    for i in 1 .. 10 loop
      dbms_lock.sleep(1);
    end loop;
  end if;
  commit;
end;
/




и пока оно работает - блокировка висит. Если прервать по OCI_BREAK, то хоть явного rollback и нету, но блокировка уйдёт, т.к. rollback будет не явный

долго доходило, но понял о чем речь. да, , release_on_commit => true тут сыграет. К сожалению в моем конкретном случае потребуется переписывать серьезно логику. Есть промежуточные фиксации транзакций при обращении к внешним системам. В автономки их просто так не вывести, а блокировку снимать нельзя.
Но как дело дойдет до планируемого рефакторинга (он рано или поздно будет) - возможно именно так и сделаю. Спасибо!
...
Рейтинг: 0 / 0
21.04.2021, 11:25
    #40064399
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
legg,

а если промежуточные фиксации обернуть вложенными автономками? (Я такого ещё не делал, не было необходимости)
...
Рейтинг: 0 / 0
21.04.2021, 11:48
    #40064405
legg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
delphinotes
legg,

а если промежуточные фиксации обернуть вложенными автономками? (Я такого ещё не делал, не было необходимости)

Что то подобное я и хотел сделать ещё до того как столкнулся с проблемой юзерлоков. Но там нужно продумать все как следует. Впопыхах делать не хочу, и наиболее безопасное решение пока что выбрал - обработка именованного исключения. Вариант некрасивый, но требует минимального вмешательства в код. Вообще эти промежуточные фиксации конечно же оч сомнительное решение имхо. Но написано до меня.
...
Рейтинг: 0 / 0
21.04.2021, 13:32
    #40064436
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как перехватить все исключения?
AlexFF__|

Чтобы сделать что-нибудь нужно иметь управление, а если клиент завершает CALL, например по Ora-01013, исполнение текущего кода прерывается.
При этом сама сессия может оставаться в добром здравии и готова к дальнейшим действиям.


Именно.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
SQL> create or replace
  2    package pkg1
  3      is
  4          g_lockname   varchar2(128);
  5          g_lockhandle varchar2(128);
  6          procedure p1;
  7  end;
  8  /

Package created.

SQL> create or replace
  2    package body pkg1
  3      is
  4        procedure p1
  5          is
  6              e exception;
  7              pragma exception_init(e,-1013);
  8          begin
  9              g_lockname := 'user_lock';
 10              dbms_lock.allocate_unique(
 11                                        lockname   => g_lockname,
 12                                        lockhandle => g_lockhandle
 13                                       );
 14              raise e;
 15            exception
 16              when others
 17               then
 18                  dbms_output.put_line('P1: ' || sqlerrm);
 19      end;
 20  end;
 21  /

Package body created.

SQL> create or replace
  2    procedure p2
  3      is
  4      begin
  5          pkg1.p1;
  6        exception
  7          when others
  8            then
  9              dbms_output.put_line('P2: ' || sqlerrm);
 10  end;
 11  /

Procedure created.

SQL> set serveroutput on
SQL> exec p2
BEGIN p2; END;

*
ERROR at line 1:
ORA-01013: user requested cancel of current operation
ORA-06512: at "SCOTT.PKG1", line 13
ORA-06512: at "SCOTT.P2", line 4
ORA-06512: at line 1


SQL> declare
  2      v_retval integer;
  3  begin
  4      v_retval := dbms_lock.release(
  5                                    lockhandle => pkg1.g_lockhandle
  6                                   );
  7  end;
  8  /

PL/SQL procedure successfully completed.

SQL>



SY.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / как перехватить все исключения? / 25 сообщений из 30, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]