Базы данных Oracle - статьи


Проблема моды изоляции чтения.


В действительности эта проблема существует, и понятно, откуда она берется: необходимо как-то учесть эффекты, связанные с тем, что пока один пользователь читает данные, другой пользователь (или другие пользователи) может эти данные изменять. Стандарт ANSI SQL-92 описывает требования к реализации нескольких т.н. мод изоляции операций чтения от выполняющихся одновременно с ним транзакций. Они варьируют от самой “слабой” моды - т.н. “незафиксированного” (часто называемого “грязным”) чтения, при котором допускается считывание данных незафиксированных транзакций, до самой “сильной” - т.н. “повторяемого” чтения, при которой гарантируется повторяемость результата при повторении операции в рамках транзакции* .Беда вся в том, что само наличие всех этих различных мод изоляции в стандарте SQL отражает отнюдь не потребности пользователей (трудно представить себе, например, разработчика приложения, заинтересованного в чтении данных чужих незафиксированных транзакций - если только он не страдает такой особой формой мазохизма), а различные степени компромисса с возможностями разработчиков СУБД. Пользователей же волнует (или во всяком случае должно волновать) совсем другое: как избежать тех неприятных эффектов, которые могут быть связаны с использованием всех стандартных мод изоляции, кроме самой “сильной” из них. Чтобы не быть голословным, рассмотрим очень простой пример. Допустим, в некоей банковской системе есть таблица, состоящая всего из двух полей:

СЧЕТА

Номер_счета

Сумма

1

100000

2

100000

3

100000

.

.

.

.

.

.

99,998

100000

99,999

100000

100,000

100000

Предположим, пользователь запустил операцию подсчета общей суммы денег на всех счетах:

select sum(Сумма) from СЧЕТА;

В любой СУБД такая операция выполняется путем последовательного перебора всех записей таблицы с подсчетом требуемой суммы. Пусть теперь другой пользователь одновременно с выполнением этого отчета (то есть после его начала, но до его завершения) проводит простую транзакцию, переводящую 50000 с одного счета на другой:

update СЧЕТА set Сумма = Сумма - 50000 where Номер_счета = 1; update СЧЕТА set Сумма = Сумма + 50000 where Номер_счета = 100000; commit;




Начало  Назад  Вперед