Выбрать главу

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 читает набор строк, возвращенный