Почему Oracle застрял после нескольких удалений?

У меня есть приложение, которое нравится:

delete from tableA where columnA='somevalue' and rownum<1000

В цикле вроде:

 while(deletedRows>0) {
    begin tran
    deletedRows = session ... "delete from tableA where columnA='somevalue' 
    and rownum<1000"....
    commit tran

}

Он запускается несколько раз (каждое удаление занимает около 20 секунд) и после долгих перерывов. Почему? Возможно ли это исправить? Благодарю.


Причина, по которой удаления выполняются в цикле, а не в виде одного оператора SQL, заключается в недостатке места отката. Смотрите этот вопрос для получения дополнительной информации.

2 ответа

Решение

Каждый раз, когда запрос сканирует таблицу с самого начала. Таким образом, он сканирует зоны, где нет строк для удаления (columnA='somevalue'). Они все дальше и дальше от первого блока таблицы.

Если стол большой и не будет columnA='somevalue' запрос займет время, чтобы проверить все строки для вашего состояния.

Что вы можете сделать, это сделать индекс на columnA, В этом случае движок будет знать быстрее, где находятся строки с этим условием (поиск по индексу выполняется в геометрической прогрессии быстрее).

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

Вы, вероятно, сталкиваетесь со многими различными проблемами. Поскольку вы говорите, что база данных работает, основная причина заключается в том, что ваша база данных работает с ошибкой ORA-00257 Archiver.

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

В зависимости от конфигурации базы данных, с точки зрения клиента, вы можете не увидеть ошибку, а просто описать поведение, когда сеанс ожидает освобождения места.

С точки зрения дизайна, я согласен с другими пользователями, что удаление в цикле не является хорошей идеей. Было бы интересно узнать, почему вы пытаетесь сделать этот цикл вместо одного оператора DELETE.

Другие вопросы по тегам