Периодически необходимо удалять или обновлять большие объёмы строк из таблиц. Например при архивировании ненужных данных прошлых периодов. Как правило, база настроена на текущие, относительно небольшие задачи , не требующих больших сегментов отката, и при большом удалении или обновлении можно наткнуться на ошибку о нехватке места в сегменте отката.

Чаще всего в такой ситуации разбивают удаляемые/обновляемые массивы строк на небольшие фрагменты по какому то принципу, и в цикле, по удалению/изменению фрагмента, выполняют COMMIT.

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

  1. Изменяется строка №1 из блока данных №1. COMMIT;
  2. блок данных №1, который уже находится в сегменте отката попал в список уже ненужных для отката блоков данных.
  3. Изменяется строка №2 из блока данных №2. COMMIT;
  4. Системе для каких то своих нужд понадобилось место в сегменте отката и она заняла освободившееся место другим блоком.
  5. Изменяется строка №3 из блока данных №1. COMMIT;
  6. Системе нужен в сегменте отката блок №1, а он уже удалён. Получаем ошибку ORA-01555

Как избежать такой ситуации ?

Самый правильный вариант - создать большой сегмент отката, который будет использоваться только в подобных случаях. Держать его в отключенном состоянии и, при необходимости, включать. Алгоритм получается такой:

  1. ALTER ROLLBACK SEGMENT BIGROLL ONLINE;
  2. COMMIT;
  3. SET TRANSACTION USE ROLLBACK SEGMENT BIGROLL
  4. Операция удаления или обновления.
  5. COMMIT;
  6. ALTER ROLLBACK SEGMENT BIGROLL OFFLINE;

Если такой вариант невозможен, то можно разбить массив строк по rowid, то есть удалить/обновить все нужные строки из одного блока, затем из другого и т.д. Через нужное количество обработанных блоков отрабатывать commit.

Хостинг от uCoz