customers все строки.
2. Т1 выполняет оператор INSERT для вставки строки в таблицу customers,
но при этом Т1 не выполняет оператор COMMIT.
3. Т2 выполняет другой оператор INSERT и снова отбирает те же самые
строки, что и на шаге 1. Т2 «не видит» новой строки, добавленной Т1
на шаге 2 .
4. Т1 в заключение выполняет оператор COMMIT, чтобы окончательно запомнить
новую строку, добавленную на шаге 2 .
5. Т2 выполняет еще один оператор SELECT, в котором теперь видна новая
строка, добавленная транзакцией Т1.
Подведем итоги: Т2 не видит изменений, сделанных Т1, пока Т1 не зафиксирует
внесенные ею изменения. Такой уровень изоляции между транзакциями
является уровнем по умолчанию. Этот уровень можно изменить
(см. ниже в разделе «Уровни изоляции транзакций»),
В таблице 8.1 показан пример операторов SQL, иллюстрирующий применение
параллельно выполняемых транзакций. Здесь показан чередующийся
порядок, в котором операторы выполняются этими двумя транзакциями
- Т1 и Т2. Транзакция Т1 выбирает строки, добавляет и обновляет строку
в таблице customers. Транзакция Т2 не видит сделанных Т1 изменений, пока
278 Глава 8
Т1 не зафиксирует их. Можно вводить показанные в таблице 8.1 операторы
и знакомиться с их результатами, запустив два отдельных сеанса
SQIfPlus и подключившись к обоим как пользователь store. Операторы
в сеансы SQL*Plus следует вводить в чередующемся порядке (см. табли-
цу 8.1 ).
Таблица 8.1. Параллельно выполняемые транзакции
Транзакция 1 Т1
(1) SELECT * FROM customers;
(3) INSERT INTO customers
(customer_id, first_name, la st_
name) VALUES (7, ‘ Jason’ , ‘ P ric e ’ );
(4) UPDATE customers SET last_name
= ‘ Orange’ WHERE customer_id = 2;
(5) SELECT *FR0M customers; Возвращенный
результирующий набор содержит
новую строку и обновление.
(7) COMMIT; Фиксирует новую строку и
обновление.
Транзакция 2 Т2
(2) SELECT * FROM customers;
(6) SELECT *FR0M customers; Возвращенный
результирующий набор не содержит новой строки
и обновлений, выполненных Т1. Он содержит
первоначальные строки, полученные на шаге 2.
(8) SELECT * FROM customers; Возвращенный
результирующий набор содержит новую
строку и обновление, выполненные Т1 на шагах
3 и 4.
Блокировка транзакций
Для поддержки параллельно выполняемых транзакций база данных должна
гарантировать, что данные в таблицах остаются правильными. Это до
стигается с помощью блокировок (locks). В следующем примере две транзакции
- Т1 и Т2 - пытаются модифицировать запись о покупателе № 1 в
таблице customers.
1. Транзакция Т1 выполняет оператор UPDATE для модификации строки
для покупателя № 1, но при этом Т1 не выполняет оператора COMMIT.
В этом случае говорят, что Т1 «блокирует» строку.
2. Транзакция Т2 также пытается выполнить оператор UPDATE для модификации
строки для покупателя № 1 , но так как эта строка уже заблокирована
транзакцией Т 1 , Т2 лишена возможности получить блокировку
для этой строки. Оператор UPDATE транзакции Т2 вынужден ждать, когда
завершится работа Т1 и со строки будет снята блокировка.
3. Транзакция Т1 завершает работу выдачей оператора COMMIT, снимая
тем самым блокировку со строки.
4. Транзакция Т2 получает блокировку на строку и выполняет оператор
UPDATE. Транзакция Т2 держит блокировку на эту строку до тех пор, пока
не закончится Т2.
Изменение содержимого таблиц 279
Подведем итоги: транзакция не может получить блокировку для строки,
если другая транзакция уже владеет блокировкой на эту же самую строку.
Примечание Наиболее простой способ понять блокировку по умолчанию заключается в следующем:
читатели не блокируют читателей, писатели не блокируют читателей, писатели блокируют
писателей только в том случае, когда они пытаются изменить одну и ту же строку.
Уровни изоляции транзакций
Уровень изоляции транзакций - это степень, до которой изменения, произведенные
одной транзакцией, отделены от других транзакций, выполняемых
параллельно. Прежде чем ознакомиться с деталями различных
уровней изоляции транзакций, необходимо понять типы проблем, которые
могут возникнуть при попытке нескольких транзакций обратиться к
одной и той же строке таблицы.
Ниже приводятся примеры с двумя параллельно выполняемыми транзакциями
Т1 и Т2, пытающимися обратиться к одним и тем же строкам
таблицы, которые иллюстрируют три типа потенциальных проблем при
обработке транзакций:
■ Фантомные чтения. Транзакция Т1 читает набор строк, возвращенный