Эта тема очень тесно связана с управлением параллелизмом, поскольку многоверсионность служит основой механизма управления параллельной обработкой Oracle. База данных Oracle действует на основе многоверсионной, согласованной по чтению модели параллелизма. В дальнейших заметках моего блога мы раскроем технические аспекты этой модели более подробно, но по существу она представляет собой механизм, посредством которого Oracle обеспечивает следующие концепции.
- Согласованные по чтению запросы. Запросы, которые создают непротиворечивые результаты конкретного момента времени.
- Неблокирующие запросы. Запросы никогда не блокируются процессом, записывающим данные, как это имеет место в других базах данных.
В базе данных Oracle эти две концепции очень важны. В основном термин многоверсионность описывает способность Oracle одновременно поддерживать несколько версий данных, извлеченных из базы (начиная с версии 3.0, вышедшей в 1983 году!).
Понятие согласованность чтения отражает тот факт, что запрос в Oracle будет возвращать результаты из согласованного момента времени. Каждый блок, используемый запросом, будет в точности соответствовать этому моменту времени, даже если данные были модифицированы или блокированы, пока выполнялся запрос (это было действительным, начиная с версии 4.0, которая появилась еще в 1984 году!). Если вы понимаете, как совместно работают многоверсионность и согласованность чтения, то всегда поймете ответы, полученные из базы данных. Прежде чем приступить к более подробному рассмотрению реализации многоверсионности в Oracle, давайте ознакомимся с ее работой на простом примере:
EODA@ORA12CR1> create table t as select username, created from all_users / Table created. Таблица создана. EODA@ORA12CR1> set autoprint off EODA@ORA12CR1> variaMe х refcursor; EODA@ORA12CR1> begin open :x for select * from t; end; / PL/SQL procedure successfully completed. Процедура PL/SQL успешно выполнена. EODA@ORA12CR1> declare pragma autonomous_ transaction; — вы могли бы также сделать это — в другом сеансе sqlplus, — и результат был begin delete from t; commit; бы идентичным end; 10 / PL/SQL procedure successfully completed. Процедура PL/SQL успешно выполнена. EODA@ORA12CR1> print х USERNME CREATE --------------------------------------------------------------------------- DEVACCT 02-SEP-13 OPS$MELANIE 17-JUL-13 SCOTT 03-JUL-13 OPS$TKYTE 02-SEP-13 АРЕХ_040200 28-JUN-13 APEX_PUBLIC_USER 28-JUN-13 AUDSYS 28-JUN-13 SYS 28-JUN-13 36 rows selected. 36 строк выбрано.
В этом примере мы создаем тестовую таблицу t и загружаем в нее данные из таблицы ALL_USERS. Затем мы открываем на этой таблице курсор. Никакие данные из курсора не извлекаются: он только открывается и остается в таком состоянии.
Затем в этом же сеансе (или, возможно, в другом - подход все равно сработал бы) мы перешли к удалению всех данных из таблицы. Мы даже выполнили фиксацию (COMMIT) этого удаления. Строки исчезли - но так ли это на самом деле? Фактически их можно извлечь через курсор (или посредством запроса FLASHBACK с применением конструкции AS OF). Дело в том, что результирующий набор, возвращенный командой OPEN, был предопределен на момент его открытия. Во время открытия мы затронули не единственный блок данных в этой таблице, но ответ уже был “высечен в камне”. У нас нет возможности узнать, каким будет этот ответ, до тех пор, пока не извлечем данные; однако с точки зрения нашего курсора результат является неизменным. Это не значит, что при открытии курсора Oracle копирует предыдущие данные в какое-то другое место; на самом деле данные сохранила для нас команда DELETE, поместив их (начальные копии образов строк, существующие до выполнения DELETE) в область данных, которая называется сегментом отмены или сегментом отката.