В Oracle минимальной единицей данных, которая может быть изменена транзакцией, является строка. Получается, что в каждый момент времени любая строка любой таблицы базы данных может находиться в одном из двух состояний:
отсутствует активная транзакция, изменившая строку (то есть когда-то ранее строка была добавлена в базу данных какой-то давнишней активной транзакцией, потом строка, возможно, изменялась предложениями UPDATE других активных транзакций, но все эти транзакции в свое время были зафиксированы или отменены);
строка изменена активной транзакцией (неважно, выполняющейся или выполненной – главное, что строка изменена, и эти изменения не зафиксированы и не отменены).
В литературе на русском языке часто встречаются фразы вроде «Запрос видит только зафиксированные данные на SCN 10023», представляющие собой кальковый перевод фраз вида «The query only sees committed data with respect to SCN 10023». Дело в том, что более правильные с точки зрения терминологии выражения выглядят довольно громоздко. Мы тоже будем дальше использовать эти ставшие общепринятыми понятия и выражения, просто приведем их определения:
зафиксированными данными называются данные, измененные зафиксированной транзакцией (изменения данных стали постоянными);
предложение SQL «видит» строки, если они используются (не игнорируются) им в ходе своего выполнения – строки участвуют в определении истинности критерия отбора из фразы WHERE и могут попадать в результирующую выборку.
Обращение к данным сервер Oracle осуществляет в одном из двух режимов:
обращение в текущем режиме (current mode, db block gets), при котором происходит обращение к строкам в их текущем состоянии, то есть в состоянии, в котором они находятся прямо сейчас (right now);
обращение в режиме согласованного чтения (consistent read mode, consistent gets), при котором происходит обращение к строкам, находящимся по состоянию на некоторый момент времени, то есть к предыдущим версиям строк.
В Oracle любой SQL-запрос SELECT видит только зафиксированные данные по состоянию на начало своего выполнения. Если другие транзакции уже после начала выполнения SQL-запроса сделают изменения в данных, и даже если эти изменения будут зафиксированы, то все равно SQL-запрос увидит версию данных по состоянию на момент начала его выполнения. Это и называется «согласованным чтением» (consistency read) на уровне отдельных предложений SQL. Часто версии данных по состоянию на некоторый момент времени в прошлом называют старыми данными.
Все сказанное верно и для критерия отбора из конструкции WHERE предложений DELETE, UPDATE и INSERT SELECT. Для удаления и изменения отбираются строки по состоянию на момент начала выполнения этих предложений.
«Под капотом» сервера Oracle для обеспечения корректного выполнения транзакций, согласованного чтения и вот этого всего имеются следующие специальные механизмы:
сегменты отката, обеспечивающие версионность данных;
система блокировок.
Блокировки
Наличие системы блокировок позволяет обеспечить корректное изменение одних и тех же данных.
Блокировкой (lock) называется средство организации доступа к совместно используемому ресурсу. Наложить на ресурс блокировку – это ограничить возможности других по работе с этим ресурсом. В Oracle есть несколько видов блокировок, мы рассмотрим, как работают самые распространенные блокировки строк таблиц транзакциями (блокировки TX).
Общие правила работы блокировок TX в Oracle выглядят так:
блокировки накладывают и снимают транзакции;
наложенную транзакцией блокировку может снять только она сама в ходе завершения транзакции командами COMMIT или ROLLBACK;
блокировки накладываются на строки таблиц (одна блокировка может накладываться на несколько строк сразу);
чтобы изменить или удалить строку, ее сначала надо заблокировать;
заблокированные одной транзакцией строки другая транзакция не может ни заблокировать, ни тем более изменить или удалить;
существует специальная форма SQL-запроса SELECT FOR UPDATE, которая накладывает блокировки на отбираемые по критерию отбора строки;
блокировки являются атрибутами самих строк – чтобы определить, есть ли на строке блокировка, к ней необходимо обратиться.
Для новых строк, добавленных в таблицу предложением INSERT, блокировка TX накладывается транзакцией, выполнившей это предложение.
При изменении строк предложением UPDATE к ним обращаются дважды:
поиск строк-кандидатов для изменений по условию в конструкции WHERE, который осуществляется в режиме согласованного чтения;
Читать дальше