Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MUMPS СУБД. Практика применения и опыт программирования.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
4.8. TSN 351
lock +name:5 e w "lock failed",!
Существуют также системы баз данных и СУБД, которые применя­ют компенсатор по таймауту автоматически, и при возникновении ситу­ации невозможности получить захват ресурса, автоматически откатыва­ют транзакцию и повторяют ее действия снова. В случае если рестарт транзакций поддерживается используемой MUMPS системой, это также может быть использовано разработчиками.
При использовании рестарта транзакций может также возникнуть ситуация, когда при выполнении N рестартов операцию выполнить все равно не удалось. В этом случае разработчики на MUMPS должны ис­пользовать значение системной переменной $TRESTART, показывающей число рестартов, чтобы процесс мог принять решение стоит ли продол­жать операцию снова. Вообще говоря, если алгоритм допускает дедлоки, то причина дедлоков не устраняется повторным запуском алгоритма, и дедлоки могут возникать при каждом его выполнении.
4.8 TSN
При выполнении транзакций СУБД должна реализовать механизм раз­личения записей в журнале транзакций, какие записи к какой транзак­ции относятся. Для этого используется так называемый номер последо­вательности транзакций, или Transaction Sequence Number (TSN).
Каждая транзакция должна получить собственный уникальный но­мер, и этот номер должен отличаться как для различных процессов од­ного экземпляра сервера СУБД, так и между процессами сервера до его останова и после последующего старта. Второе условие необходимо для корректного продолжения журнала транзакций и процедуры автомати­ческого восстановления сервера при старте.
К наиболее распространенным и достаточно устойчивым механизмам генерации номера транзакций относится алгоритм основанный на време­ни генерации с синтетическим номером выравнивания. В номер транзак­ции входит, таким образом, два числа - дата с временем и синтетическое число. Общий алгоритм состоит в следующем:
1. Сервер ведет используемую дату и синтетический номер, эти дан­ные используют процессы сервера для генерации нового значения TSN.
2. При старте сервера сервер отыскивает в журнальных записях наи­больший из последних номеров TSN и выделяет в нем дату и син­тетический номер.
352 ГЛАВА 4. КОНКУРЕНТНЫЙ ДОСТУП
3. Если текущая дата больше последней использованной, то она ста­новится используемой и синтетический номер обнуляется.
4. Если текущая дата меньше или равна используемой, то для ге­нерации TSN используется используемая, а синтетический номер увеличивается.
5. При переполнении синтетического номера используемая дата уве­личивается на одну секунду и синтетический номер обнуляется.
При такой схеме генерации значения TSN поддерживается прави­ло их непрерывного возрастания, что позволяет корректно использовать журнальные записи, оставшиеся от предыдущего сеанса работы сервера.
Кроме того, механизм генерации основанный на добавлении к те­кущей дате синтетического номера застрахован от одинаковых значений TSN, полученных при одинаковом значении времени для различных про­цессов.
Наиболее важным следствием и задачей алгоритма является устой­чивость к переводу времени на компьютере как в течении сеанса работы сервера, так и между сеансами. Такой перевод времени может выпол­няться как вручную для исправления ошибки хода часов, так и автома­тически при смене летнего и зимнего отсчета времени.
Задачей синтетического дополнения TSN является ожидание даты, когда текущая дата и время компьютера догонит используемое. В случае переполнения синтетического числа к используемому времени автомати­чески добавляется секунда и синтетический довесок обнуляется. Таким образом, если на компьютере был произведен перевод часов на N секунд назад, то сервер СУБД в течении этих N секунд будет использовать для вычисления TSN более позднее время, а когда время сравняется, начнет использовать текущее.
В случае если в реализации СУБД содержится ошибка в отноше­нии генерации очередного значения TSN, это может проявиться самым различным образом. В первую очередь либо некорректным откатом тран­закции, в течении которой был произведен перевод времени, либо некор­ректным процессом старта сервера. Если администратор системы сможет определить ситуацию сбоя, то может выполнить перевод времени на ком­пьютере соответственно либо между сеансами работы СУБД, либо во время сеанса. В любом случае, механизм генерации TSN является стро­го внутренним для СУБД, и при обнаружении проблем в работе сервера необходимо обращаться в техподдержку СУБД.
Глава 5

Обработка ошибок

5.1 Состояние ошибки

MUMPS системы относятся к средам исполнения со встроенными языко­выми средствами обработки и генерации ошибок. Уже на уровне языка присутствуют средства реагирования на нарушение обычного хода вы­полнения программы либо на невозможность его продолжения по каким­либо причинам.
Если сравнить с контекстом выполнения программы, не имеющей языковых средств обработки ошибок, то это может быть, к примеру язык С, в котором обработка отдельных типов ошибок выполняется по­разному в зависимости от типа ошибки, операционной среды, и, возмож­но, процессора. Например, обработка прерывания Ctrl+C и переполнения числа с плавающей точкой выполняются совершенно разными способа­ми, как и описание желания программы реагировать на них.
В MUMPS системах к средствам обработки ошибок относится само понятие состояния процесса при генерации ошибки, специальные коман­ды и системные переменные и функции, используя которые разработчик определяет поведение программы при возникновении ошибки. В MUMPS системах обработка ошибок, последовательность ее выполнения, набор средств обработки ошибок не зависят от типа ошибки.
Штатное выполнение программы проходит в состоянии отсутствия ошибки и последовательность выполнения определяется набором указан­ных для выполнения команд и функций. При возникновении же ошибки система выполнения должна прервать штатное выполнение программы и, не продолжая его, выполнить обработку ошибок. Обычное течение программы далее невозможно. Например, при выполнении деления на ноль или при попытке записи в базу данных находящейся в состоянии
353
354 ГЛАВА 5. ОБРАБОТКА ОШИБОК
только на чтение.
Состоянием процесса в состоянии ошибки называется перевод про­цесса в состояние невозможности продолжить выполнение следующей операции - команды, функции, вычисления оператора. Система исполне­ния при выполнении кода проверяет условия выполнимости операций, и при невозможности дальнейшей нормальной работы переводит процесс в состояние ошибки. Все непреодолимые для выполнения системой со­бытия сводятся в одно состояние - состояние ошибки. К ним относятся множество самых различных типов событий, обнаруживаемые системой исполнения, либо генерируемые программно командой генерации ошиб­ки. Это состояние существует у процесса до того момента, как будет отменено программно определенным программистом образом. И, пока процесс находится в состоянии ошибки, процесс должен предпринять специальные меры. Для того, чтобы программа не остановилась в нере­шительности, разработчик указывает, что именно необходимо предпри­нять среде исполнения MUMPS системы. К таким указаниям относится комплекс управления системой исполнения:
1. На какой из предыдущих уровней стека необходимо перейти, или необходимо ли продолжить обработку на этом же уровне стека.
2. Какой код необходимо выполнить, или на какую строку передать управление.
3. Критерий окончания обработки ошибок и перевод состояния среды исполнения MUMPS системы в состояние отсутствия ошибок.
Характер обработки ошибок указывается не всей MUMPS системе целиком с распространением требований на все выполняемые процес­сы, а индивидуально каждому процессу. У каждого процесса свои соб­ственные значения системных переменных, описывающих характер, или способ обработки ошибок.
Конечно, MUMPS система в действительности никогда не останав­ливается в нерешительности и в любом случае предпринимает действия по продолжению выполнения. И, в случае, если разработчик не указал что делать процессу при возникновении ошибки, и система исполнения не может нормально продолжить выполнение программы, то начинает искать инструкции по обработке ошибок на текущем стеке. Не найдя их, выполняет возврат на предыдущий уровень стека и снова ищет.
В случае, если система вернулась на самый верхний уровень стека в состоянии ошибки, то выполняется поведение по умолчанию - произ­водится переключение на устройство по умолчанию, вывод в текущее
5.1. СОСТОЯНИЕ ОШИБКИ 355
устройство диагностического сообщения и процесс переходит к ожида­нию ввода следующих команд. При этом система переводит процесс в состояние отсутствия ошибки, но сохраняет информацию об ошибке в специальных системных переменных. Формат диагностического сообще­ния для каждой из MUMPS системы свой и содержит порцию описания, которую система может предоставить. Обычно по такому диагностиче­скому сообщению понятно, что произошло, и зачастую где именно или с какими переменными.
Исторически сложилось так, что, хотя стандарт предусматривал со­стояние ошибки, стандартизированные средства и определение их пове­дения стандарт языка MUMPS начал предусматривать лишь с редакции 1995-го года.
MUMPS системы, разработанные до этого года, вводили обработку ошибок на свое усмотрение, и в существенной степени совместимо друг с другом по принципам поведения. При этом отдельные нюансы пове­дения различных MUMPS систем отличаются. К таким отличиям отно­сится множество сочетаний собственно обработчика ошибок с другими компонентами MUMPS системы:
1. Соотношение обработчика ошибок и состояния транзакций.
2. Сочетания поведения достандартного обработчика и стандартного, их приоритеты.
3. Возможность обработки ошибок возникших в самом обработчике ошибок.
4. Поведение встроенных команд отладки, например BREAK, ZGOTO, ZQUIT и др.
5. Наличие и содержание дополнительных системных переменных, например $ZSTATUS, $ZERROR и др.
В случае если разработчики прикладной системы используют лишь определенный стандартом обработчик ошибок, то такие программы пе­реносимы. В случае если используется достандартный, то при переносе программ разработчикам необходимо сверить поведение используемых ими нюансов таких обработчиков.
В настоящее время разработчики прикладных программ обычно вы­бирают то, что им удобнее, или то к чему они привыкли, и, зачастую, таким средством оказывается именно достандартный характер обработки ошибок.
356 ГЛАВА 5. ОБРАБОТКА ОШИБОК
Поведение достандартных обработчиков ошибок в некоторых MUMPS системах разрабатывалось зачастую с ориентацией на практичность их применения в прикладных программах, наиболее подходящих для при­менения этих MUMPS систем. Конечно, поведение таких обработчиков ошибок не было привязано к определенным прикладным программным пакетам, и было достаточно универсально, но при реализации нюансов производители MUMPS систем могли учесть наиболее предпочтитель­ные умолчания, подходящие определенным программам.
Для тех программистов, кто ранее работал со строчно - ориентиро­ванными языками, принцип построения обработчиков ошибок в MUMPS будет знаком. В частности, в языках BASIC группы до сих пор исполь­зуется синтаксическая конструкция указания что делать системе испол­нения при возникновении состояния ошибки:
On Error GoTo ОбработкаОшибок
для указания куда перейти для обработки ошибок и
On Error Goto 0
для отключения установленного ранее обработчика ошибок и перевода процесса в состояние обработки ошибок по умолчанию.
После взведения такого указания процесс уже имеет инструкцию, описывающую, что необходимо предпринять в случае возникновения ошибки. При этом инструкция обработки ошибок распространяется в за­висимости от особенностей языка либо на все дальнейшее выполнение, либо на все выполнение на текущем уровне стека. При необходимости ограничить действие обработчика ошибок нужно его взвести в соответ­ствующее состояние.
Более поздние языки с поддержкой обработки ошибок на уровне язы­ка также содержат средства ограничения области действия обработчика ошибок путем синтаксического указания этой области, например, кон­струкции вида:
try - catch try - except try - finally
Что интересно, в старших версиях Cach´e при введении блочного син­таксиса с ограничением действия фигурными скобками также был введен и обработчик ошибок с ограничением области его действия:
5.1. СОСТОЯНИЕ ОШИБКИ 357
TRY {
protected statements
} CATCH [ErrorHandle] {
error statements } further statements
В частности, обработчик деления на ноль в старших версиях Cach´e синтаксически может быть описан с использованием нового расширен­ного синтаксиса в стиле блоков try - catch и команды throw так:
div(num,div) public {
TRY {
SET ans=num/div
} CATCH errobj {
IF errobj.Name="<DIVIDE>" { SET ans=0 }
ELSE { THROW } } QUIT ans
}
В языке MUMPS, определенном как строчно - ориентированном язы­ке, вообще говоря, отсутствует такое синтаксическое понятие, как стро­ки принадлежащие или не принадлежащие функции или процедуре. По­этому в стандартном языке отсутствует как область действия обработчи­ка ошибок, так и автоматическое прекращение его действия какими либо синтаксическими элементами. Область действия определяется лишь со­стоянием стека. При этом программа может выполнять на одном и том же уровне стека самые различные строки, в том числе принадлежащие и различным рутинам.
Вообще говоря, обработка ошибок включает в себя в качестве состав­ной части определенный алгоритм передачи управления, и этот механизм может быть использован программой в качестве штатной составляющей работы процесса. Процесс можно перевести в состояние ошибки про­граммно, если процесс выполнит команду генерации ошибки. В этом случае разработчики должны понимать, что они используют механизм обработки непреодолимого состояния для возврата по стеку, который можно выполнить обычными командами. Сложно сказать, может ли это быть рекомендовано или не рекомендовано. В некоторых случаях это действительно может существенно как упростить код, так и усложнить его понимание и модернизацию.
358 ГЛАВА 5. ОБРАБОТКА ОШИБОК

5.2 ZTRAP

Механизм обработки ошибок, применявшийся в MUMPS системах до введения единого стандартизированного определения, называется обоб­щенным термином ZTRAP, поскольку производители различных MUMPS систем использовали именно этот термин.
В различных реализациях его определение и поведение различно, хотя и сохраняет общие принципы обработки ошибок - он указывает что необходимо выполнить в случае возникновения состояния ошибки и документация на конкретную MUMPS систему описывает каким именно образом он будет выполняться.
Для указания обработчика ошибок используется специальная систем­ная переменная $ZTRAP, доступная на чтение и запись. В случае если значение пусто, то это означает что система должна выполнять обра­ботку ошибок по умолчанию. Иначе система должна использовать это значение в качестве инструкции что необходимо предпринять.
Очень важно отметить, что различные реализации MUMPS систем используют различные механизмы при обработке ошибок по ZTRAP, поэтому далее будет описываться механизм с указанием MUMPS систе­мы, для которой он приведен. Кроме того, что поведение обработчиков ZTRAP в различных MUMPS системах отличается, также отличается их поведение при комбинировании с обработчиком ETRAP и их одно­временном использовании в одном процессе.
5.2.1 Cach´e
В системе Cach´e системной переменной $ZTRAP необходимо присвоить имя метки. В случае возникновения ошибки процесс выполняет неявную команду goto и переходит на эту метку. Пример:
proc ; k d proc^ZTRAP w
s $ztrap="err" w "in proc, $st=",$st,! w 1/0 w "exit proc, $st=",$st,! q
err
w "in err, $st=",$st,! q
При выполнении в терминале Cach´e получаем:
USER>k d proc^ZTRAP w in proc, $st=1 in err, $st=1
5.2. ZTRAP 359
Здесь иллюстрируется, что обработчик ошибок выполнился, не дойдя до отметки о выходе из подпрограммы, и данный обработчик выполнился на том же уровне стека.
В Cach´e есть дополнительная особенность обработчика ZTRAP: пе­ред именем метки может быть указан символ "*". Отсутствие этого сим­вола означает, что система выполнения должна вернуться до того уровня стека, на котором произошло присваивание $ZTRAP и вместо выполня­емого кода выполнить неявную команду GOTO. В случае если происхо­дит ошибка на более глубоком уровне стека, то процесс возвращается по стеку и уже на именно том уровне, где было присваивание $ZTRAP, вы­полняет обработчик ошибки. Для иллюстрации модифицируем пример:
proc ; k d proc^ZTRAP w
s $ztrap="err" w "in proc, $st=",$st,! d trap w "exit proc, $st=",$st,! q
trap
w "in trap, $st=",$st,! w 1/0
err
w "in err, $st=",$st,! q
При выполнении получаем:
USER>k d proc^ZTRAP w in proc, $st=1 in trap, $st=2 in err, $st=1
Здесь обработчик выполнился именно на том же уровне стека, где был установлен, независимо от уровня стека, где произошла ошибка ­на том же или более глубоком.
В случае если перед именем метки ставится символ "*", то это слу­жит процессу Cach´e инструкцией не выполнять развертывание стека до того уровня где был установлен обработчик, а выполнить его на том уровне стека где произошла ошибка. Проиллюстрируем еще раз моди­фицированным примером, указав уже символ "*" перед именем метки:
proc ; k d proc^ZTRAP w
s $ztrap="*err" w "in proc, $st=",$st,! d trap
360 ГЛАВА 5. ОБРАБОТКА ОШИБОК
w "exit proc, $st=",$st,! q
trap
w "in trap, $st=",$st,! w 1/0
err
w "in err, $st=",$st,! q
При выполнении примера получаем:
USER>k d proc^ZTRAP w in proc, $st=1 in trap, $st=2 in err, $st=2 exit proc, $st=1
Для того, чтобы продолжить выполнение программы с команды, сле­дующей после вызвавшую ошибку, при использовании обработчика ZTRAP в Cach´e нужно:
1. Внести код, который может вызвать ошибку, в аргумент команды XECUTE.
2. Перед именем метки с обработчиком указать символ "*".
Проиллюстрируем это на примере:
proc ; k d proc^ZTRAP w
s $ztrap="*err" w "in proc, $st=",$st,! x "w 1/0" w "exit proc, $st=",$st,! q
err
w "in err, $st=",$st,! q
При выполнении такого кода получаем:
USER>k d proc^ZTRAP w in proc, $st=1 in err, $st=2 exit proc, $st=1