Реферат: Версионность в Yukon

Все это очень хорошо работает при читающих запросах, однако при записи могут возникать конфликты. Если при выполнении обновления snapshot-транзакция доберется до записи, заблокированной другой транзакцией, то, возникнет конфликт версий. Если блокирующая транзакция успешно фиксируется, в чистом версионнике snapshot-транзакция откатывается, поскольку если она изменит данные более «молодой» транзакции и продолжит работу, вполне возможен феномен утерянного обновления. Сместить эти транзакции друг относительно друга во времени и считать snapshot-транзакцию более «молодой» тоже не получится, так как блокирующая транзакция могла добавить записи, удовлетворяющие условию выборки snapshot-транзакции, а значит, все snapshot-запросы должны были эти записи увидеть. То есть snapshot-транзакция все равно должна выполниться заново, с более поздней временной меткой, чтобы увидеть все изменения, внесенные блокирующей транзакцией.

И в данном случае Yukon мало чем отличается от версионника. Если при уровне изоляции read committed в случае изменения он может себе позволить вести себя как блокировочник, то при уровне изоляции snapshot такой фокус не пройдет. Как минимум при этом snapshot скатится все до того же read committed. Дело в том, что блокировочник уровни изоляции выше read committed обеспечивает удержанием коллективных (share) блокировок при запросах на чтение до конца транзакции. Версионник же подобных блокировок для обеспечения уровня изоляции snapshot не использует, у него принцип совсем другой. А поскольку к моменту конфликта snapshot-транзакция уже могла выполнить несколько версионных чтений, то поступать как блокировочник уже поздно, поэтому Yukon, так же как и версионник, в случае конфликта откатывает snapshot-транзакцию.

Если продолжить издевательства над таблицей tst, и изменить в ней какую-нибудь запись, не фиксируя транзакцию:

BEGIN TRAN

UPDATE tst SET y = -1 WHERE x = 3

а потом попробовать изменить ту же запись из snapshot-транзакции:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

BEGIN TRAN

UPDATE tst SET y = 3 WHERE x = 3

COMMIT TRAN

То snapshot-транзакция повиснет в задумчивости. При взгляде на блокировки, наложенные на таблицу tst, можно наблюдать картину, характерную для обычного блокировочика.

Тип Описание Объект Режим Статус spid
TAB 1963154039 IX GRANT 51
RID 1:1357:2 72057594057326592 U WAIT 51
PAG 1:1357 72057594057326592 IU GRANT 51
TAB 1963154039 IX GRANT 52
RID 1:1357:2 72057594057326592 X GRANT 52
PAG 1:1357 72057594057326592 IX GRANT 52

Таблица 3

Snapshot-транзакция (spid 52) ожидает на блокировке (U – WAIT), пока освободится нужная запись (RID 1:1357:2), заблокированная другой транзакцией (spid 51) монопольно (X - GRANT).

Если сейчас вернуться в первое окно и откатить блокирующую транзакцию, то snapshot совершенно спокойно выполнит свое обновление и зафиксируется. Однако если блокирующую транзакцию зафиксировать, то, в отличие от блокировочного поведения, snapshot-транзакция будет отменена, и клиентское приложение получит сообщение об ошибке:

.Net SqlClient Data Provider: Msg 3960, Level 16, State 1, Line 1

Cannot use snapshot isolation to access table 'tst' in database 'AdventureWorks'.

Snapshot transaction aborted due to update conflict. Retry transaction.

Более того, для отката snapshot-транзакции ей даже не нужно ожидать снятия блокировки. Чтобы избежать несогласованного изменения, необходимо производить откат даже в том случае, если после старта snapshot-транзакции одна из записей, необходимых для пишущего запроса, была изменена другой транзакцией, успевшей зафиксироваться.

Если в одном из подключений начать snapshot-транзакцию, сделав простую выборку:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

BEGIN TRAN

SELECT * FROM tst

Затем в другом подключении изменить какую-нибудь запись:

BEGIN TRAN

UPDATE tst SET y=3 WHERE x=3

COMMIT TRAN

А потом попытаться изменить эту же запись из snapshot-транзакции:

UPDATE tst SET y=3 WHERE x=3

COMMIT TRAN

К-во Просмотров: 349
Бесплатно скачать Реферат: Версионность в Yukon