|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
Коллеги, привет. Давно пишу на 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 констрейнтами. Хотел бы получить ясность для более простого случая. Ох, спасибо, что дочитали. Много вышло. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 12:02 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
я всё не читал... пользуюсь правилом: when others log record raise т.е. просто текст ошипки записать в лог, RAISE, чтоб юзер видел что - косяк ps предусмотреть и обработать все ошибки невозможно надо просто залоггировать, а там уж видно будет как исправить... это и есть концепция оракла, все ошипки пишутся в алертлрог и в трейсы, обработать все ошипки невозможно, но ты будешь видеть в логе что случилось ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 12:57 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
можно делать всё, когда понимаешь, как оно работает ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 13:02 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
shurka22Давно пишу на PL/SQL.. Обработка - строки распарсить по полям, привести в нужный формат, вставить в кучу таблиц.. а доку почитать. а все остальное лечится перезапуском джоба, если хотите с записью в лог/отправкой емайл. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 13:04 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
shurka22 (ну мало ли, патч начали ставить, а джобы забыли погасить) Вот за это сразу канделябром по голове надо... 1) imho, любая ошибка, связанная не с логикой, а с базой - повод упасть, заплакать, позвать саппорт (программиста, DBA, человека с канделябром, etc.), потому что дальнейшие проблемы прогнозировать трудно, да и не надо 2) см. пункт 1 3) см. пункт 1, 2, и выбирайте потихоньку ухватистый канделябр для тех, что требует это обрабатывать в логике 4, 5) тут надо "или трусы надеть, или крестик снять"... - или мы знаем, куда идут данные, какие там правила, и проверяем/фильтруем данные ещё до операции DML - или нам лень и мы просто пишем в лог всю запись с диагностикой (откуда, куда, почему упали), чтобы потом кто-то на это посмотрел (кто? это его обязанность? не придёт ли он с канделябром?) ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 13:04 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
насколько я помню, на уровне БД ошибка ORA-04062 signature of package has been changed не ловится или что-то поменялось? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 13:06 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
rpovarov4, 5) тут надо "или трусы надеть, или крестик снять"... - или мы знаем, куда идут данные, какие там правила, и проверяем/фильтруем данные ещё до операции DML - или нам лень и мы просто пишем в лог всю запись с диагностикой (откуда, куда, почему упали), чтобы потом кто-то на это посмотрел (кто? это его обязанность? не придёт ли он с канделябром?) Коротко: нам лень. Ну вот я тоже склоняюсь к этим двум вариантам. Максимально честный конечно же вариант 4. Но он и требует максимального кодирования, на которое постоянно нет времени. Поэтому и хотелось всё свалить на чек-констрейнты, и потом просто поймать их, залогировать, и потом по факту разобраться (разработка и бой живут близко). Собственно сейчас так и сделано. На этапе внедрения несколько раз ломались, смотрели лог, говорили, где поправить входной файл. А сейчас же уже пол-года - ничего не ломается. И вот ради чего делать двойную работу: и чек-констрейнты писать, и в коде проверять правильность заполнения. Куда проще понадеяться на констрейнт, поймать его, и сказать: мол не получилось, смотри в лог. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 14:31 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
Самое сложное в exception handling - понять, что exception в общем случае error-ом не является. Переведите дословно, помедитируйте. И примедитируете к очень простой мысли: сама концепция структурированной обработки исключительных ситуаций предназначена для спрямления логики приложения. Т.е. пишем основную мысль и отдельно описываем, что будем делать в каких-либо конкретных обстоятельствах, выводящих процесс из основного потока исполнения. При этом "все прочие" исключения логикой заведомо не предусмотрены. Посему обработчик when others по сути предназначен для самого верхнего уровня, который должен просто зафиксировать проблему и издать жалобное "мяу". Другой вопрос, что сам модуль, столкнувшийся с непредвиденной ситуацией, может быть достаточно интеллектуально развит для самостоятельной фиксации (например, логирования) собственного состояния, однако это не отменяет обязанности информировать вышестоящих - потому raise обязателен. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2018, 15:26 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
есть соседский пакет на удаленной БД я вызываю его в случае получения почты такой процедурой (на моей БД): Код: plsql 1. 2. 3. 4. 5.
раз в год пакет соседи компилируют, и у меня в ПО в бекенде валится ошибка ORA-04062: timestamp из package "*****" изменена что бы такого сделать, чтобы избежать этих ошибок ни эта процедура, ни этот пакет на моей БД в других местах нигде не вызываются ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 11:18 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
приложение - c# сессия открывается на время запуска процедуры и тут же закрывается ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 11:38 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
andreymx ORA-04062 может https://docs.oracle.com/cd/B14117_01/server.101/b10755/initparams174.htm ? это ведь о том? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 12:06 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
andreymx, в старых версиях можно было alter procedure ххх compile timestamp ууу ..... stax ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 12:55 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
Stax andreymx, в старых версиях можно было alter procedure ххх compile timestamp ууу ..... stax когда надо ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 14:09 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
legg, спасибо админы менять параметры на работающей ферме БД с десятками линков не сильно расположены ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 14:10 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
andreymx legg, спасибо админы менять параметры на работающей ферме БД с десятками линков не сильно расположены а самому для сессии устанавливать? плохое решение? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 14:13 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
legg andreymx legg, спасибо админы менять параметры на работающей ферме БД с десятками линков не сильно расположены а самому для сессии устанавливать? плохое решение? при изменении пакета user.tpkg@link валится ошибка Код: plsql 1. 2. 3.
а так вроде работает без ошибок Код: plsql 1. 2. 3. 4.
ЗЫ: перед каждым прогоном обязательно включал Код: plsql 1.
legg плохое решение? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 14:34 |
|
exception when others без raise - плохая практика?
|
|||
---|---|---|---|
#18+
andreymx legg пропущено... а самому для сессии устанавливать? плохое решение? при изменении пакета user.tpkg@link валится ошибка Код: plsql 1. 2. 3.
а так вроде работает без ошибок Код: plsql 1. 2. 3. 4.
ЗЫ: перед каждым прогоном обязательно включал Код: plsql 1.
круто. самому пригодится з.ы. умею заставить за себя поработать))) ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2021, 14:37 |
|
|
start [/forum/topic.php?fid=52&fpage=21&tid=1880260]: |
0ms |
get settings: |
9ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
84ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
55ms |
get tp. blocked users: |
2ms |
others: | 14ms |
total: | 195ms |
0 / 0 |