Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции.docx
Скачиваний:
44
Добавлен:
18.02.2016
Размер:
364.62 Кб
Скачать

Как транзакция работает

В базе данных имеется специальная область, которая называется TIP ( Transaction Inventory Page - Инвентарная Страница Транзакций). При старте транзакции, ей присваивается идентификатор ( TID, Transaction ID ) - инвентарный номер, который сохраняется в TIP. При этом у самой последней транзакции будет наибольший идентификатор. В TIP, помимо номера стартовавшей транзакции, сохраняется и ее состояние, которое может быть Active (В работе), Committed (Подтвержденная), Rolled Back (Отмененная, откат) и In Limbo (Неопределенная).

Активной называется транзакция, которая в настоящий момент выполняется.

Подтвержденной называется транзакция, которая успешно завершила свою работу, как правило, по команде Commit.

Отмененной называют транзакцию, которая завершилась неудачно. При этом производится откат сделанных ей действий, как правило, командой RollBack.

Неопределенной транзакцией ( Limbo ) называют транзакцию, которая работает одновременно с двумя или более базами данных. При завершении такой транзакции, InterBase совершает двухфазное подтверждение Commit, гарантируя, что изменения будут внесены либо во все БД, либо ни в одну. При этом подтверждения в базах данных будут даваться по очереди. Если в это время возникнет сбой системы, то может получиться, что в каких то БД изменения были сделаны, а в каких то нет. При этом транзакция переходит в неопределенное состояние, когда сервер не знает, следует ли подтвердить эту транзакцию, или откатить.

Каждая транзакция, начиная работу, создает собственную версию записей таблиц, с которыми работает. Версия записи - это копия записи, которая создается, когда транзакцияпытается ее изменить. Таким образом, каждая запись таблицы потенциально может иметь множество версий, при этом каждая транзакция работает с собственной версией этой записи. Если транзакция меняет данные, то она меняет их в собственной версии записи, а не в оригинале. Далее транзакция может либо подтвердиться, либо отмениться.

Если транзакция подтвердилась, InterBase попытается пометить предыдущую оригинальную запись, как удаленную, а версию завершенной транзакции - как оригинал. Когда InterBaseсохраняет изменения, то в новую запись помещается и идентификатор транзакции, которая внесла эти изменения (любая строка таблицы содержит идентификатор создавшей еетранзакции ).

Если транзакция завершилась неуспешно, оригинал записи так и остается оригиналом.

Если же транзакция только читает запись, не пытаясь ее изменить, то для нее не создается собственной версии.

Однако могут возникать и конфликты транзакций. Предположим, что стартовала транзакция Т1. Она создала версию записи, и поменяла ее данные. В это время стартовала конкурирующая транзакция Т2, и создала версию той же записи. Поскольку Т1 еще не завершилась, Т2 при старте не могла видеть изменения данных, сделанные Т1, а значит, создала свою версию из старого оригинала. Теперь Т1 завершает работу по Commit. Как должен поступить InterBase? Если он пометит версию записи Т1 как оригинал, а старую запись, как удаленную, то в версии Т2 окажутся ложные данные! Действия InterBase в этом случае будут зависеть от параметров этих транзакций, о чем ниже мы поговорим подробней.

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

Таким образом, говорят, что InterBase имеет многоверсионную архитектуру ( MGA - Multi Generation Architecture ). Такая архитектура позволяет организовать работу с базой данных так, чтобы читающие пользователи не блокировали пишущих. Кроме того, при возникновении сбоев в системе, InterBase очень быстро восстанавливается, благодаря именно MGA. Кстати,InterBase является первым SQL -сервером, который поддерживает многоверсионную архитектуру.

Наряду с преимуществами такого подхода, в базе данных со временем накапливается "мусор". Каждая транзакция, пытающаяся изменить данные, создает собственные версии строк, и если не позаботиться о своевременном удалении старых, уже никому не нужных версий, то база данных вскоре будет просто забита мусором.

Но как удалять мусор? Можно ли удалить версию транзакции, которая завершилась, удачно или неудачно? Нет, если эта версия в настоящий момент используется другими транзакциями. Позже мы поговорим об уровнях изолированности транзакций, пока лишь скажем, что некоторые транзакции могут видеть изменения, сделанные другими, еще не подтвержденными активными транзакциями.

Предположим, что стартовала транзакция Т1. Эта транзакция создала версию записи и модифицировала ее. Позже стартовала транзакция Т2, которая настроена так, чтобы видеть все изменения данных, даже не подтвержденные. Она обратилась к той же записи, а поскольку она желает видеть последние изменения, ей предоставляют версию транзакции Т1. Затем Т1 завершила свою работу, но Т2 пока еще работает с ее версией записи, следовательно, эту версию удалять нельзя.

В InterBase присутствует механизм удаления старых версий, который запускается новыми транзакциями. Новая транзакция, запрашивая запись, считывает все версии этой записи. При этом делается проверка на то, была ли транзакция, сделавшая эту версию, отменена ( RollBack ) или подтверждена ( Commit ). Если транзакция была отменена, значит, эта версия - мусор, который следует удалить. Если же имеется несколько версий, сделанных подтвержденными транзакциями, то актуальной считается версия с наибольшим идентификаторомтранзакций. Остальные версии считаются устаревшими и также подлежат удалению.

Таким образом, молодые транзакции прибирают базу данных от мусора, оставленного более старыми транзакциями. Но чистят они не все старые версии подряд, а только версии той записи (или записей), к которой обращаются сами.

Поскольку на сервере одновременно может выполняться множество транзакций, имеется терминология определения этих транзакций.

  • Активная транзакция - транзакция, которая стартовала, но еще не завершена.

  • Заинтересованная транзакция - это транзакция, конкурирующая с текущей транзакцией.

  • Старейшая активная транзакция - это такая активная транзакция, которая стартовала раньше других. Или иначе, это активная транзакция с наименьшим идентификатором.

  • Старейшая заинтересованная транзакция - это такая заинтересованная транзакция, которая стартовала раньше других. Или иначе, это заинтересованная транзакция с наименьшим идентификатором.

В данном контексте, сборкой мусора занимается старейшая активная транзакция. Так как версий записи, сделанных более молодыми транзакциями, она видеть не может, то убирает мусор, оставленный еще более старыми транзакциями. Когда эта транзакция заканчивает свою работу, то статус "старейшей активной" переходит к другой транзакции. Таким образом,транзакции передают друг другу обязанность по сборке мусора.