Режимы доступа к данным

Различные режимы доступа к данным - результат версионности СУБД.

Существующие режимы доступа:

Стабильные режимы, т.е. гарантирующие повторяемость чтения

  1. Мягкий (adm_SOFT). Идеально подходит для программ, которые не выполняют модификаций, а только формируют отчеты на основе данных, соответствующих определенному моменту времени.
    1. Работает на собственном срезе. Операции чтения получают версии записи со своего собственного среза. Операции модификации помещают результат на собственный срез. Получается, что если несколько мягких транзакции в качестве базового получили один и тот же срез, то собственные срезы этих транзакций могут отличаться друг от друга.
    2. Единственный режим, который работает с согласованными (целостными) данными. Они соответствуют базовому срезу.
    3. Данные базового среза со временем устаревают. Поэтому, если на основе данных мягкого режима делается некий вывод, например, формируется новая запись, то этот вывод может быть неверным, т.к. в общем случае мог быть сделан на основе устаревших данных, поскольку считанная запись уже могла быть модифицирована независимой транзакцией
    4. Доступ по чтению не сопровождается установкой блокировок, поэтому не дает конфликтов другим транзакциям, и сам не получает конфликтов. Исключения из этого правила см. здесь.
    5. Попытка монопольной модификации записи может давать конфликт:
      1. если запись модифицируется другой незавершенной транзакцией, то попытки выполнить модификацию можно периодически повторять в надежде, что мешающая транзакция откатится
      2. если запись модифицирована завершенной транзакцией, то нашей транзакции такая модификация не удастся никогда
  2. Жесткий (adm_RIDGE). До появления версионности существовал только этот  режим доступа к данным.
    1. Работает на жестком срезе.
    2. Операции позиционирования сопровождаются установкой разделяемой блокировки по стандартному правилу.
    3. Согласованность данных не гарантируются. Экземпляры различных записей могут быть результатом последовательного завершения независимых транзакций. Т.е. можно получить данные, которые ни в какой момент времени не образовывали единый срез.
    4. Получает всегда самые свежие экземпляры записей.
    5. И доступ по чтению, и монопольная модификация могут получить конфликт с блокировкой другой незавершенной транзакции (подробнее здесь). В этом случае попытки можно периодически повторять до тех пор, пока мешающая транзакция не откатится или не завершится

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

  1. Конкурентный (adm_CONCURRENT). Позволяет выполнять конкурентные модификации.
    1. Работает на жестком срезе.
    2. Операции позиционирования не сопровождаются установкой разделяемой блокировки, а значит не препятствуют выполнению модификаций, прежде всего конкурентных, в других транзакциях. Сама операция позиционирования получит конфликт при обращении к записи, заблокированной в чужой транзакции монопольно, но нет конфликта при обращении к записи, заблокированной конкурентно (подробнее здесь).
    3. Монопольные операции модификации могут выполняться, только если в собственной транзакции модифицируемая запись уже заблокирована монопольно или разделяемо, либо поставлена блокировка файла. Иначе они дают конфликт блокировок: языковые процедуры монопольной модификации выбрасывают исключение 960. Причина в том, что без предварительного захвата записи нет гарантии, что независимая транзакция не модифицировала запись конкурентно, а значит наша монопольная модификация могла бы уничтожить работу той транзакции. Само по себе переключение в конкурентный режим не создает препятствий для выполнения операции модификации в чужих транзакциях.
  2. Завершенный (adm_FINISHED).
    1. Работает на завершенном срезе. Получает самые свежие экземпляры записей без учета незавершенных транзакций
    2. Операции позиционирования не сопровождаются установкой разделяемой блокировки, а значит не получают конфликтов и не препятствуют работе других транзакций (подробнее здесь).
  3. Свежайший (adm_HOTTEST).
    1. Работает на жестком срезе. Получает самые свежие экземпляры записей с учетом незавершенных транзакций
    2. Операции позиционирования не сопровождаются установкой разделяемой блокировки, а значит не получают конфликтов и не препятствуют работе других транзакций (подробнее здесь).
  4. Обзорный (adm_BIZARRE). Совпадает со свежайшим, но если независимая незавершенная транзакция модифицировала поля уникального индекса Key, то в нашей транзакции при доступе по индексу Key дополнительно доступны экземпляры завершенного режима.

Срез, на котором выполняется работа, будем называть рабочим срезом. Это собственный срез для мягкого режима и жесткий для остальных.

  1. С помощью SE_ACCESSDATAMODE ASL-программа может переключать режим всей транзакции, на которой она выполняется, при этом все таблицы БД переключаются в этот режим. Переключить режим отдельной таблицы БД можно с помощью TABLE.AccessDataMode. Установленный режим транзакции и таблиц действует до следующей установки, до выхода из TRY-блока (любым способом), либо до завершения работы программного комплекса.
  2. Операции позиционирования и модификации выполняются в соответствии с текущим режимом таблицы. Поэтому при изменении (именно изменении, а не просто установке) стабильного режима доступа к таблице БД, позиции курсоров этой таблицы сбрасываются, если экземпляр записи курсора не соответствует новому режиму таблицы, т.е. если позиционирование на ту же запись в новом режиме может дать другой экземпляр. Правило сброса позиции:
    1. если переключение выполняется из стабильного режима или в стабильный: позиция сбрасывается, если в собственной транзакции она не заблокирована разделяемо или монопольно
    2. при переключении между нестабильными режимами позиция не сбрасывается
    Исключение из правила: переключение из BIZARRE в SOFT - позиция не сбрасывается, а перечитывается с мягкого среза.
  3. Особый случай - процедура GETLASTVERSION: ставит разделяемую блокировку, поэтому в любом режиме возвращает экземпляр жесткого среза.
  4. Транзакция может не иметь базового среза только когда ни сама транзакция, ни одна из ее таблиц не находятся в мягком режиме. Если затем вся транзакция или отдельная таблица переключается в мягкий режим, то транзакция получает базовый срез, соответствующий моменту переключения. Если после этого транзакция и все таблицы переключатся из мягкого режима, то базовый срез в транзакции останется прежним, чтобы при последующем переключении в мягкий режим работа выполнялась бы именно на этом срезе.
    Процедура RENEWDATALAYER при наличии таблиц в мягком режиме перемещает базовый срез транзакции текущей ASL-программы, делает его соответствующим моменту выполнения процедуры. Если на момент выполнения RENEWDATALAYER ни сама транзакция и ни одна таблица БД не находится в мягком режиме, то транзакция вообще теряет базовый срез.
    Наличие базового среза у транзакции T не позволяет серверу уничтожать срезы транзакций, завершенных после начала этой T. Это ведет к повышению расхода памяти на сервере. Поэтому если в ASL известно, что базовый срез жесткой транзакции T никогда больше не потребуется, то лучше с помощью процедуры RENEWDATALAYER уничтожить его, а значит позволить серверу освободить память.
  5. Если транзакция имеет базовый срез, то контроль уникальности и контроль ссылочной целостности работают с учетом базового среза. Подробнее см. SE_INTEGRITY. То же самое относится к операциям модификации группы записей.
  6. При любом режиме доступа к данным операции позиционирования учитывают конкурентные модификации, выполненные собственной транзакцией. Они накладываются на опорный экземпляр, который определяется текущим режимом доступа. Не учитываются конкурентные модификации чужих транзакций, в том числе главных, если наша транзакция подчиненная.
  7. Cхема возможных конфликтов разных режимов в разных транзакциях.
  8. Особенность работы SAVE -  RESTORE при переключении режимов.
  9. Особенности взаимодействия главной-подчиненной транзакций
    1. Подчиненная транзакция на старте наследует от ее непосредственно главной транзакции режим самой транзакции, режимы отдельных таблиц, а также базовый срез.
    2. Конфликты доступа (см. здесь)
      1. Разделяемая блокировка главной транзакции не дает конфликтов для подчиненной.
      2. Позиционирование в мягком, жестком, и конкурентном режимах в подчиненной транзакции конфликтует с монопольной блокировкой главной транзакции. В мягких транзакциях - это единственная причина конфликта при позиционировании. При этом независимая мягкая конфликт не получает, а видит старое значение.
      3. Share-блокировка и в частности GETLASTVERSION в подчиненной транзакции конфликтуют с Concurrent-блокировкой в главной. Причина: Share-блокировка гарантирует отсутствие модификаций данной позиции в незавершенных транзакциях, а значит наша транзакция пользуется актуальным на данный момент экземпляром записи. Следовательно Share-блокировка в подчиненной должна конфликтовать с Monopol- и Concurrent-блокировками главной, т.к. после завершения подчиненной главная транзакция может откатиться.
    3. На старте подчиненной транзакции текущая позиция курсора сбрасывается, если в главной транзакции она заблокирована монопольно (т.к. подчиненная не имеет доступа к записи, если она монопольно заблокирована в главной) или конкурентно (т.к. подчиненная не учитывает конкурентные модификации главной)
    4. Сразу после завершения подчиненной транзакции (даже до завершения главной) результат ее работы видит и может модифицировать любая другая транзакция: и главная, и следом запущенная другая подчиненная, и независимая.
      1. Но с учетом следующей особенности. Пример (в условиях отсутствия чужих транзакций): исходно в записи было 10 - в главной после CONCURRENTADD стало 15 - входим в подчиненную, позиция сбросилась - позиционируемся явно на ту же запись и видим 10 - CONCURRENTADD в подчиненной увеличивает значение той же записи до 13 - завершение подчиненной транзакции, и текущая позиция в главной транзакции имеет экземпляр со значением 13 (!) - последующее перепозиционирование на ту же запись дает экземпляр со значением 18. Такое поведение признано удовлетворительным, поскольку конкурентный режим не обеспечивает повторяемость чтения.
    5. Подчиненные транзакции работают на рабочем срезе главной. Это, например, означает
      1. для мягких главной-подчиненной транзакций
        1. Если подчиненная транзакция модифицировала запись и завершилась, затем независимая транзакция тоже модифицировала эту запись и завершилась или еще не успела, то главная транзакция и вызываемые после этого ее подчиненные при чтении этой записи получат результат модификации бывшей подчиненной транзакции собственного клана, но при попытке модификации этой записи они получат конфликт.
        2. Если после начала главной транзакции, но до начала подчиненной, началась, выполнила модификацию и завершилась независимая транзакция, то ни главная, ни одна из ее (транзитивно) подчиненных транзакций не увидит изменений, сделанных той независимой транзакцией, но при попытке модификации этой записи они получат конфликт.
      2. для жестких главной-подчиненной транзакций
        1. подчиненная и независимая транзакции конфликтуют друг с другом, пока обе не завершены, но когда одна из них завершается, вторая немедленно видит результат ее работы и не получает конфликтов
  10. Режимы доступа на старте системных транзакций:
    1. Интерактивные процессы, связанные с модификацией данных, а также видеопроцессы в их транзитивно подчиненных зонах (см. определение транзакции, для выполнения процессов), выполняются на жестких транзакциях.
    2. Интерактивные процессы просмотра записей в зонах, не подчиненных зонам с интерактивной модификацией, выполняются на транзакции видеосистемы.
    3. О транзакции программных событий см. здесь.
    4. Программы, запущенные с помощью RunProg на контексте зоны окна, выполняются на транзакции этой зоны. Для запуска программ не на контексте окна, создается новая жесткая транзакция.
  11. Программные события могут переключать режим доступа на время своей работы, но при их завершении режим транзакции автоматически восстанавливается, причем жесткая транзакция при этом перестает иметь базовый срез, из чего следует что она перестает препятствовать уничтожению на сервере срезов завершенных транзакций, а также что если следующая программа-обработчик переключится в мягкий режим, то она получит самый свежий базовый срез, а не тот, который был у предыдущего обработчика. Эти программные события - исключение из правила.