пакетная процедура, когда совершать транзакции? - PullRequest
0 голосов
/ 28 марта 2012

Я довольно новичок в PL-SQL, хотя у меня большой опыт работы с другими СУБД.Вот моя текущая проблема.

procedure CreateWorkUnit
is
update workunit 
set workunitstatus = 2 --workunit loaded 

where
    SYSDATE between START_DATE and END_DATE
and workunitstatus = 1 --workunit created;

--commit here?

call loader; --loads records based on status, will have a commit of its own

update workunit wu
set workunititemcount = (select count(*) from workunititems wui where wui.wuid = wu.wuid)
where workunitstatus = 2 

Таким образом, поведение, которое я наблюдаю, с или без коммитов, состоит в том, что я должен выполнить дважды.Один раз, чтобы перевернуть статусы, загрузчик запустится во втором исполнении.Я бы хотел, чтобы все было запущено за один раз.

Буду признателен за любые слова мудрости оракула. ​​

Спасибо!

Ответы [ 3 ]

4 голосов
/ 29 марта 2012

Когда совершать транзакции в пакетной процедуре?Это хороший вопрос, хотя он кажется только смутно связанным с проблемами с кодом, который вы публикуете.Но давайте все равно ответим.

Нам нужно выполнить коммит, когда процедура PL / SQL завершила единицу работы.Единица работы - это бизнес-операция.Обычно это будет в конце программы, последний оператор перед разделом ИСКЛЮЧЕНИЕ.

Иногда даже не тогда.Решение о коммите или откате должным образом принимается за вершину стека вызова.Если наш PL / SQL вызывается из клиента (может пользователь нажимает кнопку на экране), возможно, клиент должен выполнить коммит.

Но для пакетного процесса вполне разумно управлять своим собственнымcommit (и откат в случае ошибок).Но суть в том, что единственная самая верхняя процедура должна выдавать COMMIT.Если процедура вызывает другие процедуры, эти вызываемые программы не должны создавать коммитов или откатов.Если они должны обработать какие-либо ошибки (журнал и т. Д.) И повторно вызвать их в вызывающей программе.Пусть расшифрует, нужно ли откатываться.Поскольку все вызываемые процедуры выполняются в одном и том же сеансе и, следовательно, в одной и той же транзакции: откат в вызываемой программе отменит все изменения в пакетном процессе.Это не правильно.То же самое относится и к коммитам.

Иногда вы будете читать советы по использованию прерывистых коммитов для разбиения длительных процессов на более мелкие блоки, например, каждые 1000 вставок.Это плохой совет по нескольким причинам, не все они связаны с транзакциями.Соответствующие из них:

  1. Создание коммита освобождает блокировки ресурсов.Это является причиной ORA-1555 Snapshot too old ошибок.
  2. Это также влияет на согласованность чтения, которая применяется только на уровне оператора и / или транзакции.Это является причиной ошибок ORA-1002 Fetch out of sequence.
  3. Это влияет на перезапуск.Если программе не удается обработать 30% записей, можем ли мы быть уверены, что она обработает оставшиеся 70% только при повторном запуске пакета?
  4. После того, как мы зафиксировали записи, другие сеансы смогут увидеть эти изменения:для других пользователей имеет смысл видеть частично измененное представление данных?

Итак, слова «мудрости Oracle» таковы: всегда выравнивайте транзакцию базы данных с бизнес-транзакцией с помощью одного коммитаза единицу работы.


Кто-то упоминал автономные транзакции как способ выдачи коммитов в подпроцессах.Обычно это плохая идея.Изменения, сделанные в автономной транзакции, видны другим сеансам, но не нашим собственным.Это очень редко имеет смысл.Это также создает те же проблемы с перезапуском, что я обсуждал ранее.

Единственное приемлемое использование для автоматических транзакций - запись активности (журнал ошибок, трассировка, записи аудита).Нам нужны эти данные для сохранения независимо от того, что происходит в более широкой транзакции.Любое другое использование прагмы - это почти наверняка обходной путь для дизайна porr, который на самом деле только усугубляет проблему.

0 голосов
/ 29 марта 2012

Я неправильно классифицировал свою проблему. Я думал, что это была проблема транзакции, и на самом деле это был один из моих флагов, который не был установлен должным образом. Числовое поле было нулевым, когда я ожидал 0.

Извините за это. Джош Робинсон

0 голосов
/ 28 марта 2012

Возможно, вам не нужно фиксировать в процедуре pl / sql.процедуры, которые вы вызываете внутри другой процедуры, будут использовать тот же сеанс, поэтому вам не нужно фиксировать.кстати процедура должна полностью откатываться, если у нее сеанс откатывался или есть исключение.

...