Здравствуйте, Аноним, Вы писали:
А>Что за "вероятность неупорядоченности" и почему она сохраняется ? Ведь от фантомов snapshot избавляет?
Немного не так, Snapshot избавляет от
фантомных чтений, но ряда других, не столь очевидных проявлений фантомов, и феноменов (аномалий) избежать, используя только Snapshot не получится.
Ссылку на один пример Синклер уже дал. Примечательно то, что в Юконе, при snapshot IL, данный сценарий отработает совершено корректно. И никаких нарушений последовательного выполнения транзакций не произойдет.
Так же, одной из классических аномалий, от которой snapshot не избавляет, и которую можно отнести к разновидности фантомов является Write Skew:
Допустим бизнес-логика требует, чтобы x+y<5, на данный момент x=1 и y=1, далее псевдокод:
-- для всех транзакций
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
-- транзакция 1 (T1)
--
SELECT (X, Y)
-- надо добавить к X два,
-- проверяем, что X + 2 + Y < 5
--
IF ((X + 2) + Y < 5) -- все в порядке Y(=1) + X(=1+2)<5
UPDATE SET X=X+2
-- в этот момент стартует вторая транзакция
-- которой, в свою очередь, надо к Y добавить 2, естественно с проверкой.
--
SELECT (X, Y)
IF (X + (Y + 2) < 5) -- тоже все в порядке Y(=1+2) + X(=1)<5
UPDATE SET Y=Y+2 -- так как SELECT(X, Y) выбрал последнюю
-- зафиксированную версию X (=1)
-- ну и фиксируем обе транзакции в произвольном порядке.
--
COMMIT -- T1
COMMIT -- T2
В многоверсионной истории это выглядит примерно так:
R1(x,y),W1(x),R2(x,y),W2(y),C1..,C2
Как нетрудно догадаться, в результате этих упражнений X+Y будет равно 6, что не соответствует никакому сценарию последовательного выполнения этих транзакций.
А>И зачем нужны фиктивные изменения? Я никогда не слышал, чтобы при работе с ораклом приходилось что-то фиктивно менять, а это "версионник".
Ну, все-таки, Оракл не совсем версионник и в силу этого у него есть хинт FOR UPDATE, как раз для таких случаев, как Write Skew. Если в примере, приведенном выше, выборку SELECT (x,y), в Оракле, делать с хинтом FOR UPDATE, то все сразу станет мягким и шелковистым. Эффект от выполнения этих транзакций всегда будет строго последовательным.
Но, честные версионники такой возможности не имеют, например, в InterBase'е, на сколько мне известно, чтобы избежать подобных аномалий необходимо делать фиктивный update X и Y в обеих транзакциях, перед тем, как считывать их значения.
Если же взять первый пример, ссылку на который дал Sinclair, то там не спасет и FOR UPDATE, и фиктивный UPDATE.
В силу отсутствия предикатных блокировок у всех известных мне версионников, в том сценарии поможет только блокировка всей таблицы.
А>2. А как добиваются Serializable? Блокируется вся таблица?
Вся таблица блокируется только в случае отсутствия индексов, если же находится подходящий индекс, то блокируется диапазон значений (Key Range Lock), что гораздо эффективнее.
Впрочем, подходящую ссылку так же уже привели..