Почему 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.