Можно ли заменить точки сохранения для запуска новых транзакций в Oracle?
Прямо сейчас процесс, который мы используем для вставки наборов записей, выглядит примерно так:
(и обратите внимание, что "набор записей" означает что-то вроде записи человека вместе с его адресами, номерами телефонов или любыми другими объединенными таблицами).
- Начать транзакцию.
- Вставьте набор записей, которые связаны между собой.
- Подтвердите, если все прошло успешно, откатитесь иначе.
- Вернитесь к шагу 1 для следующего набора записей.
Должны ли мы делать что-то более подобное?
- Начать транзакцию в начале скрипта
- Начните точку сохранения для каждого набора записей.
- Вставьте набор связанных записей.
- Откатитесь до точки сохранения, если есть ошибка, продолжайте, если все прошло успешно.
- Зафиксируйте транзакцию в начале скрипта.
После некоторых проблем с ORA-01555 и прочтения нескольких статей Ask Tom (например, этой) я подумываю попробовать второй процесс. Конечно, как отмечает Том, начало новой транзакции должно определяться потребностями бизнеса. Стоит ли опробовать второй процесс или это плохая идея?
2 ответа
Транзакция должна быть значимой единицей работы. Но то, что составляет Единицу Работы, зависит от контекста. В системе OLTP единица работы - это один человек, вместе с информацией об адресе и т. Д. Но звучит так, как будто вы реализуете какую-то форму пакетной обработки, которая загружает много людей.
Если у вас есть проблемы с ORA-1555, это почти наверняка, потому что у вас есть длительный запрос, предоставляющий данные, которые обновляются другими транзакциями. Фиксация внутри вашего цикла способствует циклическому использованию сегментов UNDO и, следовательно, будет увеличивать вероятность того, что сегменты, на которые вы полагаетесь для обеспечения согласованности чтения, будут повторно использованы. Так что не делать это, вероятно, хорошая идея.
Решение о том, использовать ли SAVEPOINTs - это другой вопрос. Я не уверен, какое преимущество это даст вам в вашей ситуации. Поскольку вы работаете с Oracle10g, возможно, вам следует вместо этого использовать массовую регистрацию ошибок DML.
В качестве альтернативы вы можете переписать управляющий запрос, чтобы он работал с небольшими порциями данных. Не зная больше о специфике вашего процесса, я не могу дать конкретный совет. Но в целом, вместо того, чтобы открывать один курсор для 10000 записей, может быть лучше открыть его двадцать раз для 500 строк в поп. Другая вещь, которую стоит рассмотреть, - можно ли сделать процесс вставки более эффективным, скажем, с помощью массового сбора и FORALL.
Некоторые мысли...
- Мне кажется, что одним из пунктов ссылки на asktom было определение размера отката / отмены, чтобы избежать 1555-х годов. Есть ли какая-то причина, по которой это невозможно? Как он отмечает, купить диск гораздо дешевле, чем писать / поддерживать код, чтобы справиться с ограничениями отката (хотя мне пришлось сделать двойной дубль после прочтения ценовой метки в 250 долларов США для накопителя на 36 Гб - этот поток начался в 2002 году! Хорошая иллюстрация закона Мура!)
- Эта ссылка (Burleson) показывает одну возможную проблему с точками сохранения.
- Является ли ваша транзакция действительными шагами 2,3 и 5 по второму сценарию? Если так, то это то, что я бы сделал - зафиксировать каждую транзакцию. Звучит немного как сценарий 1 - это совокупность транзакций, объединенных в одну?