Транзакции.
Транзакцией называют
последовательность действий, в которой должны
быть выполнены либо все действия, либо ни одного.
В ASB такими действиями в транзакции
можно считать
С каждой транзакцией связаны некоторые
объекты и проассоциированы некоторые действия, и
про то и про другое можно говорить, что они
принадлежат данной транзакции, поскольку другие
транзакции не имеют права с ними работать. Это
- курсоры
- блокировки
- выполненные модификации данных на
диске
В ASB неотъемлимой частью транзакций
являются уровни транзакций. Транзакция
может содержать любое количество вложенных друг
в друга уровней, но хотя бы один уровень обязан
присутствовать. На самом деле блокировки и
модификации данных проассоциированы именно с
уровнем транзакции.
Работу с уровнем транзакций схематично
можно представить так:
Начать K-й уровень некой транзакции T.
Выполнить различные действия,
ассоциированные с K-м уровнем транзакции T,
возможно некоторые из них выполнить на K+1-м
уровне транзакции T.
- Окончить работу с K-м уровнем
транзакции T, текущим становится K-1-й уровень.
Возможны два варианта:
- Завершить уровень. Все модификации
данных, а также явно или неявно установленные
блокировки, ассоциированные с K-м уровнем,
ассоциируются с K-1-м уровнем транзакции T, т.е. два
уровня как бы сливаются. Состояние курсоров,
данных на диске и т.п. не изменяется.
- Откатить уровень. Все записи,
модифицированные на уровне K транзакции T,
принимают значения, которые они имели до начала
этого уровня, явно или неявно установленные на
данном уровне блокировки снимаются. Курсоры
транзакции T, над которыми на уровне K выполнялись
операции модификации или позиционирования,
начинают содержать позиции, которые они
содержали на момент начала уровня K.
Окончание первого уровня транзакции
является окончанием транзакции.
Работу с использованием транзакций
схематично можно представить так:
Создать транзакцию T.
Начать 1-й уровень транзакции T.
Выполнить некоторые действия,
ассоциированные с уровнем 1 транзакции T.
Начать 2-й уровень транзакции T.
Выполнить некоторые действия,
ассоциированные с уровнем 2 транзакции T.
...
Выполнить некоторые действия,
ассоциированные с уровнем 2 транзакции T.
Окончить 2-й уровень транзакции T.
Выполнить некоторые действия,
ассоциированные с уровнем 1 транзакции T.
Окончить 1-й уровень транзакции T - это и есть окончание
транзакции.
Уничтожить транзакцию T.
Возможны два варианта окончания работы с транзакцией.
- Зафиксировать транзакцию. При этом все
модификации данных, выполненные в этой
транзакции сохраняются на диске, явно или неявно
установленные блокировки снимаются, т.е. новые
версии данных становятся доступными для других
транзакций.
- Откатить все действия, выполненные в
транзакции. При этом все записи,
модифицированные в данной транзакции принимают
значения, которые они имели до начала транзакции,
явно или неявно установленные блокировки
снимаются.
Каждое подключение может вести одновременно несколько
транзакций. Несвязанные между собой транзакции,
выполняющиеся на одной станции, будем называть параллельными.
Пример параллельных транзакций - это
редактирование записей двух несвязанных между
собой файлов базы данных. Параллельные
транзакции не могут одновременно модифицировать
одни и те же данные. Этому мешает принцип
взаимодействия блокировок параллельных
транзакций, а блокировками автоматически
сопровождается любая операция модификации.
Точно также, как и параллельные, ведут себя
транзакции, выполняющиеся на разных станциях
сети, поэтому и те и другие вместе будем называть
единым термином независимые транзакции.
Друг про друга независимые транзакции ничего не
знают. Они могут только почувствовать, что некая
другая транзакция мешает им поставить
блокировку некоторой записи или файла или выполнить
операцию модификации.
Совсем иначе в этом отношении ведет себя
подчиненная транзакция. Это полноценная
транзакция, обладающая всеми описанными выше
свойствами. Она тоже позволяет завести
несколько вложенных уровней; ставит собственные
блокировки и снимает их при завершении работы; может окончиться либо
фиксацией всех выполненных модификаций данных, либо откатом. Но она имеет рад
особенностей:
- Подчиненная транзакция наследует от главной режим доступа к данным
всей транзакции и всех ее таблиц БД, а также привилегию прав доступа (см.
GRANT_ALL_RIGHTS),
базовый срез
- Особое
взаимодействия блокировок главной и подчиненной транзакций. Кратко можно охарактеризовать так: подчиненная транзакция имеет полный доступ
к записям, разделяемо заблокированным в главной транзакции, но не
имеет никакого доступа к записям, монопольно заблокированным в
главной транзакции. Иначе могла бы возникнуть ситуация, что воспользовавшись
этими данными подчиненная транзакция завершится фиксацией, а затем главная
откатится, и результат работы подчиненной окажется неверным, т.к. она
работала с "несуществующими" экземплярами данных.
-
На старте подчиненной транзакции позиции языковых
курсоров не меняются.
Но если в главной транзакции позиция курсора заблокирована
монопольно или конкурентно, то при входе в подчиненную курсор теряет позицию. Причина в
недоступности позиций, монопольно заблокированных главной транзакцией.
-
Позиции курсоров при окончании подчиненной транзакции определяется
параметром RESTORE_CURSORS TRY-блока.
-
Некоторые процедуры требуют предварительной блокировки, например,
SAVE, REPLACE. Подчиненная
транзакция использует разделяемые блокировки главной транзакцией, как
свои собственные, т.е. наследует их.
Дополнительно о взаимодействии главной - подчиненной - независимой
транзакций с учетом версионности см.
здесь.
В ASB не имеется средств для явной работы с транзакциями - нет возможности
подать команды "создать транзакцию", "начать или завершить некий уровень
транзакции" и т.п. Это происходит автоматически:
- Для следующих событий при интерактивной работе
в видео-окне
- вход в редактирование записи
- вставки новой записи
- удалении записи
- изменение состояния метки записи
- запуск программы на событие уровня зоны
- запуск программы при помощи опции RunProg
если текущее окно является зависимым,
то работа выполняется на транзакции зоны, порождающей транзакцию
для данного окна, а если порождающая транзакцию
зона отсутствует, то эта работа выполняется на
собственной параллельной транзакции. Если
текущее окно является независимым,
то работа выполняется на собственной параллельной
транзакции.
- Создается новая параллельная транзакция и
начинается ее первый уровень
- при запуске NTF-программы
- На вложенном уровне транзакции работают
- программы уровня поля
- программы уровня записи
- TRY-блоки в ASL-языке
- В ASL при выполнении TRY с атрибутом
TRANSACTION
создается подчиненная транзакция по отношению к
транзакции вызывающей программы.
Принцип версионного подхода основан на том, что транзакция, модифицируя
запись файла БД,
порождает новую копию (версию, экземпляр) этой записи, с которой в дальнейшем и работает.
В зависимости от режима доступа к данным, транзакция может видеть или не видеть
экземпляр, порожденный чужой транзакцией. Если транзакция T модифицировала
запись R, то даже после успешного завершения T, устаревшая версия записи R сохраняется в
памяти сервера для обеспечения мягкого режима доступа в незавершенных транзакциях, стартовавших до
завершения работы T.
Набор версий всех записей всех файлов БД доступных конкретной транзакции в конкретный момент
времени будем называть транзакционным срезом данных или для
краткости просто срезом. При версионном подходе каждая транзакция в процессе
работы формирует новый срез, но результат ее работы, т.е. тот самый срез,
становится виден только после завершения работы этой транзакции и только для
транзакций, начавшихся после ее завершения. Транзакции имеют продолжительное
время работы, поэтому несколько транзакций могут работать параллельно, но
завершаются они обязательно последовательно, последовательно формируя
транзакционные срезы.
С точки зрения конкретной транзакции можно выделить несколько различных типов
срезов (в порядке от более древних к более свежим):
- Устаревшие срезы. Некоторые из них могут еще существовать в памяти
сервера, но большинство уже всеми забыто. Данными этих срезов транзакция не
пользуется никогда
- Базовый срез. Это самый свежий завершенный срез, существовавший
на момент начала данной транзакции. Понятно, что
для каждой транзакции базовый срез индивидуален. Но в начале своей работы
несколько транзакций могут получить в качестве базового один и тот же срез.
- В процессе работы транзакция может модифицировать данные, формируя
новый, пока еще незавершенный, срез. Такой срез будем называть
собственным срезом транзакции. Условно можно считать, что в момент
старта транзакция получает собственный срез, как копию базового среза, после
чего она может собственный срез модифицировать.
- Когда транзакция завершается, ее собственный срез приобретает статус
"завершенный" и может стать базовым для новых транзакций. С точки зрения
незавершенных на этот момент транзакций такой срез будем называть "более
свежим завершенным срезом" или для краткости просто завершенным, т.к.
устаревшие (очевидно тоже завершенные) срезы транзакциями вообще никогда не
рассматриваются и можно считать, что и не существуют.
- Самый свежий завершенный срез в конкретный момент времени будем
называть последним завершенным срезом или для краткости просто последним.
Очевидно, что именно последний срез для стартующей транзакции становится
базовым.
- Жесткий срез - набор самых свежих версий всех записей всех
файлов БД в конкретный момент времени, причем не важно, принадлежат эти
версии завершенным или незавершенным транзакциям. Т.к. любую запись может
модифицировать только одна незавершенная транзакция, то жесткий срез -
это вполне конкретное понятие. Но в отличии от всех предыдущих этот срез
нестабилен и меняется с течением времени.
Наличие таких типов срезов позволяет использовать различные
режимы доступа к данным.
См. примеры, демонстрирующие новое
поведение версии 12.64.1