powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / exception when others без raise - плохая практика?
18 сообщений из 18, страница 1 из 1
exception when others без raise - плохая практика?
    #39741892
shurka22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги, привет.
Давно пишу на PL/SQL, но так и не пришёл к выводу, хорошо ли ловить exception when others без raise.

Вот пример:
на входе куча записей (сырые строки, поля через запятую) на обработку. Время от времени поднимается джоб и все их пытается обработать.
Обработка - строки распарсить по полям, привести в нужный формат, вставить в кучу таблиц по некоторым правилам. Если обработать не получается - метим запись, как плохую, и переходим к следующей записи.
Запись на обработку хоть и формируется софтом (не руками), но могут быть ошибки, запись некорректно сформирована, не по формату, или всё по формату, но данные не ложатся в наши текущие данные (например стреляются форин-кеи, уникальные ключи, или чек-констрейнты).

0) преобразование поля из строки в дату или число - проблемы нет, каждое преобразование to_number или to_date обложено when others - и кричим, мол, неверный формат такого-то поля.
Проблема возникает при отлове застрела констрейнтов в операциях DML.

1) Первая версия обработки была написана "в лоб":
всё вставляем по таблицам. Если где застрелился констрейнт - ловим others в одном месте (в самом конце процедуры обработки одной записи), откатываем транзакцию (roolback to savepoint), в лог пишем стек ошибки (чтобы можно было понять, что именно сломалось), и метим запись как плохую. Переходим к следующей записи.
Беда-1 (самая большая беда) с таким подходом такая: если вдруг какой-то пакет (вызываемый в обработке) невалиден (ну мало ли, патч начали ставить, а джобы забыли погасить), то моментально все записи метятся как плохие.
Но на самом деле лучше бы остановить джоб и сказать: мол, ребята, у вас что-то с базой не то, почините, и начните сначала.
Беда-2 такая, что мы не знаем, что именно плохо во входящей записи. Но обычно это всё откатывается на тестах, и на бою проблемы крайне редки, и в случае сбоя нет критики подождать пару дней, пока разработчик выйдет на работу. На эту беду можно не обращать внимания.

2) подход 2: ловим others, и если SQLCODE один из:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body ... has been invalidated
ORA-06508: PL/SQL: could not find program unit being called: ...
делаем raise, чтобы остановить джоб.
По факту этот подход сейчас доминирует во всём написанном до меня коде.

3) Предыдущий подход хорош. Но есть подозрение, что этих ошибок недостаточно.
Например можно raise делать и для ошибки
ORA-04062 signature of package has been changed
или того хуже:
ORA-01033 ORACLE initialization or shutdown in progress
И создаётся ощущение, что этот путь не имеет конца. raise надо делать чуть ли не на любой ошибке.

4) Можно обложить каждую операцию вставки записи в каждую таблицу адовым количеством проверок: заменить этой логикой оракловые констрейнты: и чек-констрейнты, и форин-кеи, и уникальные ключи, итд.
Но это как-бы двойная работа: сначала мы в таблице пишем ограничения, а потом ещё и в коде их проверяем, чтобы не дай бог не застрелился табличный констрейнт.

5) Можно в конце блока обработки ловить строго те ошибки, которые создаются при операциях DML:
ORA-00001: unique constraint .. violated
ORA-02291: integrity constraint .. violated - parent key not found
ORA-01400: cannot insert NULL into ...
ORA-01407: cannot update .. to NULL
ORA-02290: check constraint .. violated
Но что-то опять создаётся ощущение (зря?), что этот набор ошибок сильно не полный.

Какой подход рекомендуют выбрать лучшие оракловоды?
Томкайт - он так вообще экстремист, и хотел бы запретить others (I truly wish we didn't even support WHEN OTHERS.)
Пишет, "ловите только то, что вы ожидаете получить":
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::p11_question_id:1155066278457

Я тут не привожу более сложный пример с deferred констрейнтами. Хотел бы получить ясность для более простого случая.
Ох, спасибо, что дочитали. Много вышло.
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #39741914
казинак
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я всё не читал...
пользуюсь правилом:
when others
log record
raise

т.е. просто текст ошипки записать в лог,
RAISE, чтоб юзер видел что - косяк

ps
предусмотреть и обработать все ошибки невозможно
надо просто залоггировать,
а там уж видно будет как исправить...

это и есть концепция оракла,
все ошипки пишутся в алертлрог и в трейсы,

обработать все ошипки невозможно, но ты будешь видеть в логе что случилось
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #39741917
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
можно делать всё, когда понимаешь, как оно работает
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #39741920
123йй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shurka22Давно пишу на PL/SQL..
Обработка - строки распарсить по полям, привести в нужный формат, вставить в кучу таблиц..
а доку почитать.
а все остальное лечится перезапуском джоба, если хотите с записью в лог/отправкой емайл.
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #39741921
rpovarov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
shurka22 (ну мало ли, патч начали ставить, а джобы забыли погасить)

Вот за это сразу канделябром по голове надо...

1) imho, любая ошибка, связанная не с логикой, а с базой - повод упасть, заплакать, позвать саппорт (программиста, DBA, человека с канделябром, etc.), потому что дальнейшие проблемы прогнозировать трудно, да и не надо

2) см. пункт 1

3) см. пункт 1, 2, и выбирайте потихоньку ухватистый канделябр для тех, что требует это обрабатывать в логике

4, 5) тут надо "или трусы надеть, или крестик снять"...
- или мы знаем, куда идут данные, какие там правила, и проверяем/фильтруем данные ещё до операции DML
- или нам лень и мы просто пишем в лог всю запись с диагностикой (откуда, куда, почему упали), чтобы потом кто-то на это посмотрел (кто? это его обязанность? не придёт ли он с канделябром?)
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #39741922
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
насколько я помню, на уровне БД ошибка ORA-04062 signature of package has been changed не ловится
или что-то поменялось?
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #39741972
shurka22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rpovarov4, 5) тут надо "или трусы надеть, или крестик снять"...
- или мы знаем, куда идут данные, какие там правила, и проверяем/фильтруем данные ещё до операции DML
- или нам лень и мы просто пишем в лог всю запись с диагностикой (откуда, куда, почему упали), чтобы потом кто-то на это посмотрел (кто? это его обязанность? не придёт ли он с канделябром?)
Коротко: нам лень.
Ну вот я тоже склоняюсь к этим двум вариантам. Максимально честный конечно же вариант 4. Но он и требует максимального кодирования, на которое постоянно нет времени. Поэтому и хотелось всё свалить на чек-констрейнты, и потом просто поймать их, залогировать, и потом по факту разобраться (разработка и бой живут близко). Собственно сейчас так и сделано. На этапе внедрения несколько раз ломались, смотрели лог, говорили, где поправить входной файл. А сейчас же уже пол-года - ничего не ломается. И вот ради чего делать двойную работу: и чек-констрейнты писать, и в коде проверять правильность заполнения. Куда проще понадеяться на констрейнт, поймать его, и сказать: мол не получилось, смотри в лог.
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #39742014
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Самое сложное в exception handling - понять, что exception в общем случае error-ом не является.
Переведите дословно, помедитируйте.
И примедитируете к очень простой мысли: сама концепция структурированной обработки исключительных ситуаций предназначена для спрямления логики приложения.
Т.е. пишем основную мысль и отдельно описываем, что будем делать в каких-либо конкретных обстоятельствах, выводящих процесс из основного потока исполнения.
При этом "все прочие" исключения логикой заведомо не предусмотрены.
Посему обработчик when others по сути предназначен для самого верхнего уровня, который должен просто зафиксировать проблему и издать жалобное "мяу".
Другой вопрос, что сам модуль, столкнувшийся с непредвиденной ситуацией, может быть достаточно интеллектуально развит для самостоятельной фиксации (например, логирования) собственного состояния, однако это не отменяет обязанности информировать вышестоящих - потому raise обязателен.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
exception when others без raise - плохая практика?
    #40064672
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть соседский пакет на удаленной БД
я вызываю его в случае получения почты такой процедурой (на моей БД):
Код: plsql
1.
2.
3.
4.
5.
CREATE OR REPLACE PROCEDURE proc_mail(p_letter_id  NUMBER)
AS
BEGIN
    execute IMMEDIATE 'begin pkg_proc_mail.job_proc_mail@remote(:p_letter_id); end;' USING p_letter_id;
END;


раз в год пакет соседи компилируют, и у меня в ПО в бекенде валится ошибка
ORA-04062: timestamp из package "*****" изменена

что бы такого сделать, чтобы избежать этих ошибок

ни эта процедура, ни этот пакет на моей БД в других местах нигде не вызываются
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064676
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
приложение - c#
сессия открывается на время запуска процедуры и тут же закрывается
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064687
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx
ORA-04062

может
https://docs.oracle.com/cd/B14117_01/server.101/b10755/initparams174.htm ?
это ведь о том?
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064705
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx,

в старых версиях можно было

alter procedure ххх compile timestamp ууу

.....
stax
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064735
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
andreymx,

в старых версиях можно было

alter procedure ххх compile timestamp ууу

.....
stax
знать бы
когда надо
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064737
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg,

спасибо

админы менять параметры на работающей ферме БД с десятками линков не сильно расположены
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064740
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx
legg,

спасибо

админы менять параметры на работающей ферме БД с десятками линков не сильно расположены

а самому для сессии устанавливать? плохое решение?
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064753
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg
andreymx
legg,

спасибо

админы менять параметры на работающей ферме БД с десятками линков не сильно расположены

а самому для сессии устанавливать? плохое решение?
потестил

при изменении пакета user.tpkg@link валится ошибка
Код: plsql
1.
2.
3.
BEGIN
    user.tpkg.i1@link(1);
END;



а так вроде работает без ошибок
Код: plsql
1.
2.
3.
4.
BEGIN
    execute IMMEDIATE 'ALTER SESSION set REMOTE_DEPENDENCIES_MODE = SIGNATURE';
    user.tpkg.i1@link(1);
END;





ЗЫ: перед каждым прогоном обязательно включал
Код: plsql
1.
ALTER SESSION set REMOTE_DEPENDENCIES_MODE = TIMESTAMP;





legg
плохое решение?
в моём случае вполне приемлемое. У меня короткоживущая сессия только для этой задачи
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064754
legg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx
legg
пропущено...

а самому для сессии устанавливать? плохое решение?
потестил

при изменении пакета user.tpkg@link валится ошибка
Код: plsql
1.
2.
3.
BEGIN
    user.tpkg.i1@link(1);
END;




а так вроде работает без ошибок
Код: plsql
1.
2.
3.
4.
BEGIN
    execute IMMEDIATE 'ALTER SESSION set REMOTE_DEPENDENCIES_MODE = SIGNATURE';
    user.tpkg.i1@link(1);
END;






ЗЫ: перед каждым прогоном обязательно включал
Код: plsql
1.
ALTER SESSION set REMOTE_DEPENDENCIES_MODE = TIMESTAMP;


круто. самому пригодится
з.ы. умею заставить за себя поработать)))
...
Рейтинг: 0 / 0
exception when others без raise - плохая практика?
    #40064756
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
legg
круто. самому пригодится
щаз посмотрим, что гуру скажут
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / exception when others без raise - плохая практика?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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