Что произойдет при вставке строки во время длинного запроса
Я пишу некоторый код загрузки данных, который извлекает данные из большой медленной таблицы в базе данных Oracle. У меня есть доступ только для чтения к данным, и я не могу изменять индексы или каким-либо образом влиять на скорость запроса.
Мой оператор select занимает 5 минут и возвращает около 300000 строк. Система постоянно вставляет большие партии новых записей, и мне нужно убедиться, что я получаю каждую последнюю запись, поэтому мне нужно сохранить метку времени для последней загрузки данных.
Мой вопрос: если моя инструкция выбора выполняется в течение 5 минут, и новые строки вставляются во время выполнения выбора, получу ли я новые строки или нет в результате запроса?
Моя интуиция говорит мне, что ответ "нет", тем более что большая часть этих 5 минут - это просто время, потраченное на передачу данных из базы данных в локальную среду, но я не могу найти никакой прямой документации по сценарию,
1 ответ
"Если моя инструкция выбора выполняется в течение 5 минут, а новые строки вставляются во время выполнения операции выбора, получу ли я новые строки или нет в результате запроса?"
Нет. Oracle обеспечивает строгие уровни изоляции и не допускает грязного чтения.
Уровень изоляции по умолчанию - Read Committed. Это означает, что набор результатов, который вы получите через пять минут, будет идентичен тому, который вы получили бы, если бы Oracle мог доставить вам все записи за 0,0000001 секунды. Все, что было зафиксировано после начала выполнения запроса, не будет включено в результаты. Это включает в себя обновления записей, а также вставки.
Oracle делает это, отслеживая изменения в таблице в табличном пространстве UNDO. При условии, что он может ограничить исходное изображение от этих данных, ваш запрос будет выполнен до конца; если по какой-либо причине информация об отмене будет перезаписана, ваш запрос потерпит неудачу с ужасом ORA-1555: Snapshot too old
, Правильно: Oracle скорее выдаст исключение, чем предоставит нам несовместимый набор результатов.
Обратите внимание, что эта согласованность применяется на уровне операторов. Если мы выполним один и тот же запрос дважды в одной транзакции, мы можем увидеть два разных набора результатов. Если это проблема (я думаю, что не в вашем случае), нам нужно переключиться с Read Committed на Serialized изоляцию.
Руководство по понятиям подробно описывает параллелизм и последовательность. Узнать больше.
Поэтому, чтобы ответить на ваш вопрос, возьмите временную метку с момента запуска выбора. В частности, возьмите max(created_ts)
из таблицы, прежде чем начать запрос. Это должно защитить вас от пробела, который упоминает Алекс (если записи не зафиксированы в момент их вставки, существует вероятность потери записей, если вы выбираете выбор по сравнению с системной меткой времени). Хотя это означает, что вы отправляете два запроса в одной транзакции, что означает, что вам все-таки нужна последовательная изоляция!