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

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

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

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

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

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

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

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


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

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

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

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

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

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


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

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


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

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

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


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

SY.

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

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

Никак.
Чтобы сделать что-нибудь нужно иметь управление, а если клиент завершает CALL, например по Ora-01013, исполнение текущего кода прерывается.
При этом сама сессия может оставаться в добром здравии и готова к дальнейшим действиям.
...
Рейтинг: 0 / 0
как перехватить все исключения?
    #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
как перехватить все исключения?
    #40064352
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg

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

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

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

Есть мнение, что если процедура что-то делает и в случае успеха выполняет коммит, то процедуру стоит оформить в виде автономной транзакции.
Конкретно с Ora-01013 не проверял, но, т.к. автономная транзакция должна выполнять rollback в случае необработанных ошибок, думается это может сработать (и блокировки должны сняться сами при выходе из процедуры как при завершении сессии).
...
Рейтинг: 0 / 0
как перехватить все исключения?
    #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
как перехватить все исключения?
    #40064376
delphinotes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
legg,

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


(либо оберни вызов своей процедуры в другую с этой прагмой и дёргай из клиента обёртку)
...
Рейтинг: 0 / 0
как перехватить все исключения?
    #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
как перехватить все исключения?
    #40064391
delphinotes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
legg,

а вызвать dbms_lock.request с параметром release_on_commit => true религия не позволяет?
...
Рейтинг: 0 / 0
как перехватить все исключения?
    #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
как перехватить все исключения?
    #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
как перехватить все исключения?
    #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
как перехватить все исключения?
    #40064399
delphinotes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
legg,

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

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

Что то подобное я и хотел сделать ещё до того как столкнулся с проблемой юзерлоков. Но там нужно продумать все как следует. Впопыхах делать не хочу, и наиболее безопасное решение пока что выбрал - обработка именованного исключения. Вариант некрасивый, но требует минимального вмешательства в код. Вообще эти промежуточные фиксации конечно же оч сомнительное решение имхо. Но написано до меня.
...
Рейтинг: 0 / 0
как перехватить все исключения?
    #40064436
Фотография 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
25 сообщений из 30, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / как перехватить все исключения?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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