История СУБД Линтер начинается в 1980 году, в период становления теории реляционных систем обработки данных. У системы были свои отечественные предшественники, в разработке которых принимали непосредственное участие создатели СУБД ЛИНТЕР. К 1983 году в Воронежском СКТБ «Системпрограмм», в рамках государственного заказа, был завершен проект реляционной СУБД БАРС под управлением операционной системы реального времени РАФОС (прототип RT-11) для машин семейства СМ ЭВМ.

Рис. 1. Основные направления развития СУБД Линтер

С 1985 года разработчиками системы была принята концепция мобильности, совместимости и открытости, результатом реализации которой стало к 1990 году создание семейства совместимых СУБД для большинства используемых в то время вычислительных платформ [1-2]. Данная система была представлена под названием СУБД ИНТЕРЕАЛ и охватывала широкий спектр программно-аппаратных платформ: от ЭВМ Электроника-85 и управляющих модулей на базе Intel 8086 до вычислительных комплексов на базе СМ1702, Электроника 82, и их прототипов семейства VAX.

В 1990 году коллективом разработчиков СУБД было основано научно-производственное предприятие РЕЛЭКС (Реляционные экспертные системы), основной идеей которого было создание и использование передовых технологий в области СУБД. В то время ставилась задача совместить преимущества и достоинства персональных и больших профессиональных СУБД. [3] Исходной базой таких технологий и стала система нового, для того времени, поколения ЛИНТЕР.

Последующий период развития системы определялся направленностью в сторону соответствия международным стандартам в области обработки данных, расширением функциональности до уровня больших профессиональных СУБД, активным участием разработчиков в практическом применении системы для различных пользовательских задач, реализацией собственными силами ряда крупных корпоративных проектов, созданием специализированных версий под заказ и выходом на рынок в США.

Примечательной особенностью системы является разработка комплекса средств защиты СУБД ЛИНТЕР и сертификация в 1997 году Гостехкомиссией России ее соответствия на 2-ой класс защищенности по показателям защищенности от несанкционированного доступа к информации. Эта возможность реализована для операционных систем Windows NT, Unix и NetWare. Таким образом, СУБД ЛИНТЕР может быть использована при разработке автоматизированных систем до классов защищенности 3А и 2А включительно.

Современные направления развития технологий Линтер находятся в полном соответствии с актуальными задачами профессиональных СУБД ближайших лет.

В их числе: развитие языков доступа к данным; технологий хранения данных; реализация объектно-реляционных технологий баз данных; поддержка распределенных БД; реализация концепций информационных систем, ориентированных на анализ данных; обеспечение защиты данных в условиях распределенной обработки. Одной из ключевых задач является обеспечение надежной работы СУБД в режиме «24 часа х 365 дней».

Архитектура

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

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

СУБД ЛИНТЕР позволяет выполнять следующие действия:

  • использовать полный набор возможностей стандартного языка SQL (American National Standard X3.135-1992), а также расширения возможностей стандарта;
  • удалять/изменять/добавлять объекты базы (данные, индексы, таблицы, хранимые процедуры, триггеры);
  • вводить/изменять/удалять ограничения целостности данных;
  • блокировать/деблокировать доступ к таблице/записи;
  • сохранять/восстанавливать базу данных целиком или некоторые ее объекты выборочно, устанавливать расписание и систему сохранения;
  • транслировать запросы (с параметрами и без) и использовать уже оттранслированные запросы для ускорения работы приложения;
  • работать с большими (до 2-ух гигабайт) байтовыми объектами (BLOB);
  • осуществлять импорт и экспорт наиболее популярных форматов хранения данных;
  • использовать (в приложениях и хранимых процедурах) различные режимы обработки транзакций;
  • создавать и использовать гибкую и надежную систему безопасности и секретности информации (ЛИНТЕР имеет Сертификат Гостехкомиссии при Президенте РФ на соответствие второму классу защищенности данных от несанкционированного доступа к информации). Необходимо отметить, что на данный момент столь высокий класс защиты из СУБД, представленных в России, не имеет никто;
  • создавать, отлаживать и запускать хранимые процедуры и триггеры;
  • использовать возможности реального времени (приоритеты выполнения транзакций, асинхронное выполнение запросов, отслеживание процессов, проходящих в системе, приостановка и полная остановка работы указанной транзакции и пр.).
Рис. 2. Структура Линтер

Последние два пункта особенно важны при подготовке многозадачной прикладной системы и дают возможность пользователю настроить ЛИНТЕР на конкретные приложения и максимально ускорить работу системы.

Структура программного обеспечения ЛИНТЕР показана на рис. 2.

 

 

 

Основные характеристики системы

Итак, СУБД ЛИНТЕР - открытая многопользовательская реляционная система, использующая для доступа к данным язык запросов SQL. Число таблиц в базе данных может находиться в промежутке между 1 и 65535. Каждая таблица может содержать 250 столбцов и 33.554.431 строк. Максимальная длина строки 4.000 байт. Количество ключей в таблице ограничено только количеством столбцов. Длина ключа ограничена 128 байтами. Минимальный уровень блокирования данных - запись. Максимальное число таблиц в запросе (на одном уровне) - 32.

Индекс в СУБД ЛИНТЕР строится по B?-дереву, данные и индексы таблицы хранятся в сжатом виде, кроме того, есть эффективный механизм переиспользования табличного пространства.

Система поддерживает четыре режима обработки транзакций: Optimistic, Pessimistic, Autocommit, Read-only.

Файлы и файловая система

СУБД ЛИНТЕР хранит каждую таблицу в виде набора файлов и пользуется всеми возможностями, которые предоставляет файловый процессор операционной системы.

Так, в многопользовательских/сетевых системах доступность файлов базы данных для пользователя (минуя доступ через СУБД) отслеживается операционной системой.

Еще одна возможность, которой пользуется ЛИНТЕР, - это расширяемость файлов. Эта возможность позволяет тратить меньше усилий на расчет размера файлов таблицы, реже модифицировать ее физическую структуру, но чрезмерное увлечение этой особенностью может привести к малоэффективному использованию дискового пространства и, соответственно, к уменьшению скорости. Если пользователь имеет точное представление об объеме и характере данных прикладной системы, то лучше однажды выделить место под файл. Последний при этом окажется «более непрерывным» и, следовательно, более эффективным при работе с СУБД.

Ядро ЛИНТЕР использует файловый процессор операционной системы, добавляя к нему еще и свой аппарат, который более осведомлен о характере процессов ввода/вывода из файлов базы. Ядро ведет свой пул элементов ввода/вывода и использует свои алгоритмы буферизации/блокировок параллельно с операционной системой. Сочетание алгоритмов, учитывающих особенности СУБД, и универсальных алгоритмов операционной системы дает хорошие результаты.

Многозадачная среда

ЛИНТЕР - открытая система, предназначенная для использования в многозадачных операционных средах, поэтому алгоритмам распараллеливания обработки запросов уделялось пристальное внимание. При этом максимально используется то распараллеливание, которое дает операционная система, и, в дополнение к этому, ядро СУБД проводит собственное распараллеливание обработки запросов. Алгоритм обработки запросов ведется несколькими задачами (ядро, транслятор запросов, транслятор хранимых процедур, сортировщик ответов), распараллеливанием работы которых занимается операционная система.

Ядро, как реентерабельная программа, принимает пришедший на обработку запрос, ставит его в ряд параллельно обрабатываемых запросов и, квантуя обработку этих запросов, переключается с одного запроса на другой.

Широкие возможности настройки ЛИНТЕР позволяют сделать конкретную многозадачную прикладную систему более эффективной. Более того, в системе предусмотрены средства слежения за распараллеливанием, которое проводит ядро. Пользуясь ими можно точнее установить эффективные параметры настройки системы или понять, что и в какой момент мешает общему потоку запросов, поступающих от пользовательских задач. Средства слежения позволяют системному аналитику определить профиль работы СУБД, получить полезные рекомендации и сделать конкретные выводы по настройке ЛИНТЕР для более рационального использования его ресурсов.

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

Что реализовано в системе

Мобильность

ЛИНТЕР работает на многих программно-аппаратных платформах (рис. 3).

Рис. 3. Многоплатформная СУБД ЛИНТЕР

Кроме инвариантности интерфейса относительно поддерживаемых операционных систем, ЛИНТЕР мобилен также и по программному интерфейсу. Это означает, что при переносе прикладной информационной системы на другую платформу не возникает проблем, связанных с программными интерфейсами.

Следующий уровень мобильности - мобильность по данным. Совместимость по данным - наиболее важный момент при работе в разнородной сети. При работе в условиях гетерогенной сети СУБД ЛИНТЕР полностью обеспечивает совместимость данных с той техникой и операционной системой, которая находится на узле сети, запросившем эти данные.

Масштабируемость

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

Почти все процессы, участвующие в обработке запросов на сервере (собственно ядро ЛИНТЕР, SQL-транслятор, транслятор хранимых процедур, сортировка, сетевой драйвер сервера) настраиваются на использование дополнительной памяти. Использование дополнительной памяти этими компонентами серьезно увеличивает эффективность работы системы.

Зависимость эффективности от числа процессоров сервера не столь яркая. ЛИНТЕР - многозадачная СУБД. В процессе обработки запросов принимает участие несколько задач: ядро, SQL-транслятор, транслятор хранимых процедур и процессор сортировки (может быть, даже не один). При этом все может быть организовано таким образом, что различные из указанных задач будут выполняться на различных процессорах. И это дает определенный выигрыш в эффективности.

В следующих версиях СУБД ЛИНТЕР будет осуществлен переход к использованию различных процессоров при обработке запросов внутри ядра. Причем принят самый интересный вариант - выполняться на различных процессорах смогут не только различные запросы, но даже и различные части одного запроса. При наличии высококачественных интерфейсов ввода-вывода (например, SCSI, RAID-массивы) ЛИНТЕР будет использовать их возможности по параллельному исполнению нескольких запросов на ввод-вывод.

Увеличение количества пользователей СУБД ЛИНТЕР в рамках вычислительной сети не вызывает никаких трудностей и ограничено только физическими возможностями конкретного сетевого протокола. А благодаря драйверу JDBC, входящему в стандартную поставку ЛИНТЕР, и возможностям, предоставляемым Internet, количество пользователей системы, работающей под управлением ЛИНТЕР можно сделать практически неограниченным.

Распределенность

Концепция распределенности СУБД ЛИНТЕР позволяет прозрачно обрабатывать запросы к данным, находящимся в различных базах данных вне зависимости от их физического расположения и обеспечивает равноправный доступ пользователей к разным базам данных, расположенным в различных узлах вычислительной сети.

Основным понятием концепции является сетевое или логическое ЛИНТЕР-имя, которое представляет собой восьмисимвольный идентификатор, хранящийся в специальном файле ЛИНТЕР-имен - nodetab. В этом файле ЛИНТЕР-имена связаны с сетевыми параметрами узла запуска ядра ЛИНТЕР.

Кроме того, ЛИНТЕР-имя однозначно определяет в текущей операционной среде базу данных, для которой будет запущено независимое ядро СУБД ЛИНТЕР. Части выполняемого запроса, которые необходимо выполнить именно в данной базе будут переправляться по указанному в nodetab адресу с использованием ЛИНТЕР-имени.

Список баз данных (ЛИНТЕР-имен), которые могут участвовать в процессе выполнения распределенных запросов, содержится в специальной системной таблице - SERVERS. Эта таблица входит в системный словарь базы данных и подчиняется стандартным правилам работы со словарями, принятым в СУБД ЛИНТЕР.

В SERVERS хранится имя, по которому работает СУБД внутри и которое будет передано вовне для определения, на какой из удаленных серверов нужно пересылать запрос за недостающими данными. В SERVERS не хранится связь имени с сетевой конфигурацией. Таким образом, при изменениях конфигурации (через файл nodetab) трансляция имен внутри базы данных останется неизменной.

Создание/удаление узла распределенной базы данных производится специальным SQL-запросом CREATE/ DROP NODE.

Теперь о технологии распределенности в СУБД ЛИНТЕР.

Главный компонент аппарата распределенности - loltp - процесс, который работает с удаленным сервером. Он принимает запрос от локального ядра во внутреннем формате и формирует из него SQL-запрос к удаленному серверу. Соответственно, при этом используется сетевой клиентский драйвер.

На данный момент локальное ядро и сам loltp работают с запросами синхронно, всегда ожидая ответа (локальное ядро от loltp и само loltp от удаленного сервера). Однако фирма Релэкс ведет работы по разработке асинхронной технологии.

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

Журнализация

Основой надежности работы СУБД ЛИНТЕР с данными является системный журнал или журнал транзакций. В файле журнала отображаются все изменения, производимые над данными всеми пользователями системы.

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

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

Итак, ЛИНТЕР при исправлении неполных/неверных данных может либо вернуть их в то состояние, в котором они находились до изменений (откат изменений), либо продолжить модификацию данных следуя журналу транзакций (прокрутка вперед). При этом используется следующее простое правило: если пользователь получил «уведомление» о том, что его изменения перенесены в базу, то при следующем запуске системы новые данные обязаны находиться в базе.

Режимы транзакций

В ЛИНТЕР четыре основных стратегии (или режима) работы транзакций.

Оптимистичная (Optimistic Concurrency Control). Модификации данных не поступают в базу, однако, поступают в системный журнал вместе со старым образом данных. При фиксации изменений транзакции система начинает перенос изменений из журнала в базу данных.

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

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

Пессимистичная (Pessimistic). Это классический режим работы транзакций. Все изменения поступают сразу в базу данных, а также и в системный журнал. Однако эти изменения не видны другим транзакциям до тех пор, пока не пройдет ее фиксация и пока работает аппарат блокировок, запрещающий модификацию читаемых или чтение модифицируемых данных.

Autocommit. В принципе в этом режиме система работает по той же схеме, что и в pessimistic, но с принудительным commit после каждого предложения SQL.

Тупиковые ситуации (взаимоблокировки или DeadLock?) разрешаются обычно в пользу более высокоприоритетной транзакции, а при равном приоритете в пользу той транзакции, которая проработала большее время.

Стратегия read-only. Удобный режим транзакций, которые не делают никаких изменений в базе данных, их функция - только чтение (например, отчеты за день, сведение данных для анализа и т.п.). Обычно такие транзакции вовлекают в свою работу большие объемы данных, так что блокировка всех используемых данных может привести к длительной задержке прочих транзакций.

В ЛИНТЕР транзакция read-only не блокирует данные. Но при ее появлении, все другие транзакции, изменяя данные, оставляют (для нее и ей подобных) тот образ, который имели данные, когда транзакция read-only стартовала.

Таким образом, транзакция read-only получает базу данных именно на момент ее старта, как бы моментальный «снимок» базы данных.

Промежуточные точки синхронизации (savepoint). В СУБД ЛИНТЕР каждое приложение может использовать расширение протокола обработки плоских транзакций - промежуточные точки синхронизации транзакции savepoint. Установка промежуточной точки синхронизации реализуется предложением set savepoint . Все savepoint являются именованными. Все savepoint одной транзакции упорядочены во времени, каждая из этих точек отмечается в журнале транзакций.

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

rollback to savepoint 
      
commit to savepoint 
      

Операция «commit to» savepoint снимает все промежуточные точки синхронизации, начиная от начала текущей транзакции до данной savepoint, и фиксирует работу транзакции от ее начала до данной точки. Операция «rollback to» savepoint снимает промежуточные точки синхронизации, начиная от данной savepoint, и откатывает все операции, которые были выполнены после операции установки savepoint.

Иерархия транзакций. В СУБД ЛИНТЕР каждое приложение может использовать как обычные плоские транзакции, так и иерархические.

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

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

Несомненно, это слишком категоричный и, следовательно, не всегда приемлемый принцип. Особенно в системах с нечеткой логикой.

Например, приложению нужно произвести три действия A, B и D в одной транзакции. Причем действия A и D являются необходимыми, а вот для действия B есть «запасной вариант» - действие C. Так что приложение пытается в первую очередь выполнить действие B, и только если по какой-либо причине результаты отработки B «не устраивают» или возникла ошибка, то изменения, сделанные B, откатываются, и приложение предпринимает резервное действие C.

Такую логику транзакции не удастся реализовать при помощи линейных транзакций. Для использования подобных транзакций СУБД ЛИНТЕР предоставляет пользователю возможность иерархии транзакций.

При этом действуют следующие правила.

1. Подчиненные (вложенные) транзакции являются плоскими транзакциями или плоскими транзакциями с savepoint. И могут работать зависимо или независимо друг от друга в любом из режимов (от оптимистичного до read-only).

2. Каждая из подчиненных транзакций может быть фиксирована/откачена независимо от других подчиненных транзакций.

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

4. Фиксация/откат головной транзакции приведет к фиксации/откату всех подчиненных и не завершенных (на данный момент) транзакций.

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

Реальное время. В ЛИНТЕР реализовано несколько возможностей, выделяющих эту СУБД из ряда аналогов. Это свойства, которые позволяют отнести ЛИНТЕР к системам реального времени.

Во-первых, это возможность подачи запросов в асинхронном режиме. Отметим, что имеется в виду полнокровная асинхронность с определением процедуры обработки ответа, которая включится только тогда, когда программа будет прервана пришедшим от ЛИНТЕР ответом на запрос.

Во-вторых, ЛИНТЕР может обрабатывать запросы в соответствии с установленными для них приоритетами. Более важные (приоритетные) будут выполнены раньше низкоприоритетных, им будут отданы системой все возможные ресурсы.

В-третьих, аппарат событий ЛИНТЕР позволит приложению устанавливать особые ситуации и обеспечивать реакцию на их возникновение. Например, какая-то задача прикладной системы SQL-запросом устанавливает событие A (например, модификация данных). Другие задачи могут запросить чтобы их оповестили о возникновении события A. По возникновению этого события, запросившие его задачи, будут прерваны, включатся соответствующие процедуры обработки ответа (на запрос об оповещении). По окончании обработки события (например, после того, как были повторно запрошены измененные данные), программа продолжится с того места, где она была прервана.

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

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

Далее отметим возможность слежения из приложения за состоянием использования ресурсов ядра СУБД, что позволяет написать задачу с супервизорскими функциями. Такая задача следит за процессами, происходящими в ядре ЛИНТЕР, и может решить, что обработка какого-то запроса требует слишком много ресурсов, и приостановить или прервать его обработку.

Конфиденциальность

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

Рис. 4. Обеспечение политики безопасности

В СУБД ЛИНТЕР политика безопасности реализуется с помощью двух основных подсистем:

  • подсистемы управления доступом к информации,
  • подсистемы поддержания высокой готовности информации.

В СУБД ЛИНТЕР реализован ряд методов управления доступом к информации (рис.5):

Рис. 5. Методы управления доступом

Авторизация пользователей производится при установлении соединения с системой. Проверке подлежит регистрационное имя пользователя и его пароль. Если процесс авторизации пользователя прошел успешно, то все дальнейшие запросы к СУБД по установленному соединению однозначно связываются с данным пользователем.

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

Дискреционная защита в СУБД ЛИНТЕР реализована с помощью аппарата привилегий, которые можно подразделить на две категории: привилегии безопасности (позволяют выполнять административные действия) и привилегии доступа (определяют права доступа конкретных субъектов к определенным объектам).

Привилегии безопасности. Таких привилегий (категорий пользователей) три.

Администратор базы данных - категория DBA. Это управляющий созданием БД, ее конфигурированием, регистрацией пользователей, групп, ролей, записью регистрационной информации и т.п.

Привилегированные пользователи БД - категория RESOURCE. Это пользователи, которые имеют право на создание собственных объектов БД и управление привилегиями доступа к ним.

Пользователи БД - категория CONNECT оперируют с объектами БД в рамках выделенных им привилегий доступа.

Привилегии доступа:

  • SELECT - на выборку данных;
  • INSERT - на добавление данных;
  • DELETE - на удаление данных;
  • UPDATE - на обновление данных;
  • ALTER - на изменение параметров таблицы;
  • INDEX - на создание/удаление индексов;
  • ALL - включает все вышеперечисленные права доступа.

Эти привилегии может присваивать/изымать только владелец соответствующих объектов - таблиц, представлений и синонимов. Привилегии можно объединять в роли.

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

Мандатная защита предназначена для построения информационных систем с высокой степенью защищенности и состоит в назначении различных уровней ценности для всей хранимой информации.

Для этого в СУБД ЛИНТЕР используются метки доступа. Метка доступа состоит из трех частей: группы доступа (именованная совокупность пользователей) и двух уровней доступа.

Для субъектов базы данных они называются: уровень доверия пользователя (WAL) и уровень доступа пользователя (RAL). Для объектов базы данных они называются: уровень чтения данных (RAL) и уровень доступа данных (WAL).

Метки доступа могут быть назначены всем субъектам базы и объектам, начиная от таблиц и до полей записей включительно.

Реализованная модель защиты препятствует следующим видам нарушений:

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

Контроль доступа с удаленных станций или сопоставление пользователя с устройством позволит учитывать различный уровень защищенности самих клиентских станций. При правильной политике безопасности ЛИНТЕР не допустит использование канала связи, в котором ценная информация может быть получена пользователем, не обладающим соответствующими правами доступа.

Основополагающим понятием в процессе сопоставления пользователя с устройством является понятие сетевого устройства. Сетевым устройством в ЛИНТЕР считается любое устройство, имеющее уникальный идентификатор - адрес в сети. Каждое сетевое устройство в ЛИНТЕР характеризуется целой совокупностью параметров (адрес устройства, тип сети, тип подсети, маска разрешенного времени доступа, уровни мандатного доступа, маска разрешенных групп).

Разрешенные времена доступа могут быть указаны вплоть до временных интервалов в течение дня.

Протоколирование работы или система слежения ЛИНТЕР применяется для контроля функционирования подсистемы защиты, обнаружения попыток несанкционированного доступа, исправления их последствий и предотвращения их в будущем.

В СУБД ЛИНТЕР производится протоколирование широкого спектра событий. Для того, чтобы информация об определенном событии заносилась в журнал, необходимо выставить флаг протоколирования этого события.

В журнал системы безопасности заносятся следующая информация:

  • отметка времени;
  • имя пользователя;
  • имя объекта;
  • группа события;
  • тип события;
  • статус завершения ЛИНТЕР.

Сюда же заносится дополнительная информация о клиентской станции (сетевой адрес, PID клиента, сокет клиента), с которой пришел запрос.

Регулярный мониторинг журнала системы безопасности позволяет поддерживать надежность системы защиты на высоком уровне и своевременно реагировать на попытки обойти систему защиты.

Контроль за хранением информации со стороны СУБД ЛИНТЕР позволяет учитывать различный уровень защищенности внешних устройств постоянного хранения информации для размещения таблиц данных и временных рабочих файлов. Например, часть таблиц может быть расположена на диске сервера, находящегося в охраняемом помещении, а часть размещена на жестком диске другой ЭВМ или даже на гибком диске. Защищенность устройства в последнем случае гораздо более низкая, и, следовательно, здесь не может быть расположена секретная информация.

Доступ к устройству в ЛИНТЕР может быть разрешен/запрещен различным группам пользователей. Кроме того, устройству назначается метка доступа, характеризующая его уровень защищенности и ограничивающая степень секретности содержащейся на нем информации.

В СУБД ЛИНТЕР каждое устройство характеризуется следующей информацией:

  • идентификатором устройства;
  • именем устройства;
  • физическим путем к устройству;
  • описанием устройства;
  • параметрами доступа к устройству.

Удаление остаточной информации закрывает еще один канал нелегального доступа к недоступным данным - анализ остаточной информации. Анализу поддается как информация в оперативной памяти, так и информация во внешней памяти. Для предотвращения этого в обоих случаях освободившееся пространство очищается с помощью записи маскирующей информации.

Поддержка высокой готовности информации. Помимо механизмов управления доступом к информации в СУБД ЛИНТЕР существуют механизмы поддержки высокой готовности информации. Под этим подразумевается обеспечение доступа к информации в режиме реального времени, гарантированная независимость целостности и сохранности информации от сбоев в системе, от попыток разрушения информации, от аварийных ситуаций различного рода и т.д.

Совместимость

Тот факт, что язык запросов SQL ЛИНТЕР основан на международном стандарте, говорит о высокой совместимости системы. Кроме того, в SQL ЛИНТЕР введены многие элементы, обеспечивающие совместимость с другими системами, главным образом с СУБД Oracle.

Интерфейсные утилиты системы ориентированы на стандарт CUA. Пользователь, привыкший к аналогичным системам, легко освоит работу и в среде ЛИНТЕР.

Рис. 6. Драйверы, реализованные в СУБД «Линтер»

Интерфейс ODBC позволяет осуществлять максимальную переносимость приложения с одной СУБД на другую без учета их специфики. Поэтому в связи с совместимостью, конечно же, необходимо упомянуть об ODBC-драйвере ЛИНТЕР (спецификация - ODBC 3.0), а это значит, что все существующие средства разработки и то, что опирается на ODBC-стандарт, будут работать с СУБД ЛИНТЕР без ограничений.

ЛИНТЕР JDBC (спецификация JDBC 1.2) позволяет писать приложения на Java, используя СУБД ЛИНТЕР. Java-программа может быть разработана в виде апплета, загружаемого через Internet и запускаемого на стороне клиента, или в виде приложения, постоянно находящегося на стороне клиента. В любом случае интерфейс JDBC позволяет Java-приложению подключаться к удаленным базам данных, направлять к ним запросы и получать результаты обработки запросов.

При этом реализованы следующие типы драйверов (рис. 6).

  • Pure Java client - клиент полностью написан на Java. Налицо преимущества этого типа - реализация классов на Java позволяет получить набор реализующих классов и использовать их в клиентском апплете. К недостаткам этого типа можно отнести невысокую производительность из-за медлительности java.net.*.
  • Native-Java client - кроме классов, реализующих интерфейс JDBC, для работы необходимо иметь динамически подключаемую библиотеку трансляции вызовов к СУБД ЛИНТЕР. К недостаткам этого типа можно отнести необходимость инсталляции этой библиотеки, зато это даст существенный выигрыш в скорости (в три-пять раз по сравнению с использованием драйвера типа Pure Java клиент).

Основные сетевые протоколы, поддерживаемые системой: TCP/IP, IPX/SPX, DECNet.

Имеются средства конвертации данных из DBF-формата, имеются программные интерфейсы для работы с ЛИНТЕР из Clipper, FoxPro.

Отметим так же совместимость ЛИНТЕР с СУБД Oracle на уровне Pro?C и OCI. Благодаря библиотеке OraLin, приложение, работающее с СУБД Oracle, будет с таким же успехом работать (после перекомпоновки, а в Windows, в случае использования динамически подгружаемых библиотек, и без нее) и с ЛИНТЕР, совершенно не заметив подмены. Кроме того, для более полной совместимости с СУБД Oracle был расширен синтаксис языка запросов, который в данный момент поддерживает многое из того, что и Oracle SQL, вплоть до иерархических запросов. Таким образом, благодаря всем перечисленным возможностям, для многочисленных пользователей Oracle переход к использованию СУБД ЛИНТЕР не составит большого труда.

Имеется также средство - LinTcl, которое расширяет возможности Tcl/Tk для работы с СУБД ЛИНТЕР, что позволяет использовать Tcl/Tk для быстрого написания информационных приложений в операционных средах, в которых работает Tcl/Tk (Unix, Windows).

Средства разработки

Intcom - 4-GL

Язык Intcom предназначен для создания прикладных информационных систем и ориентирован на прикладного программиста. Являясь языком четвертого поколения, Intcom содержит средства для организации экранного интерфейса (ориентация на стандарт CUA - Common User Access) и доступа к базам данных ЛИНТЕР (на основе стандарта ANSI SQL-92).

Перечислим особенности языка Intcom.

  • Это коммерческий язык. В нем упор делается на быструю подготовку программ, удобных для использования непрофессионалами.
  • Язык содержит простые конструкции для организации удобной и эффективной работы пользователя за терминалом.
  • Язык прост для освоения и использования. Это достигается высоким уровнем языка, простотой и жесткостью его конструкций.
  • Intcom - специализированный язык. Его применение в некоторых областях (например, в системах численного анализа) затруднено, а порой (в системах реального времени) и невозможно.
  • Язык Intcom - часть системы ЛИНТЕР. Поэтому, проектируя прикладную информационную систему на Intcom, необходимо, как минимум, хорошо знать структуру базы данных этой прикладной системы.
  • Intcom, как и система ЛИНТЕР, мобильный язык. Программа на Intcom будет одинаково работать на любой платформе, где функционирует ЛИНТЕР.

Пользовательский интерфейс, подготовленный на языке Intcom, ориентирован на поддержку стандарта CUA (Common User Access), интерфейс с LINTER на стандарт ANSI SQL-92.

«Лакуна»

Инструментальное средство «Лакуна» предназначено для быстрой разработки приложений типа клиент-сервер, ориентированных на обработку данных с использованием СУБД ЛИНТЕР. Разработка приложений средствами «Лакуны» выполняется в интерактивном режиме с хранением кода в служебных таблицах базы. В окончательном виде приложение представляет собой набор структур данных (документов) и правил (процедур) их обработки.

Проектирование приложений существенно упрощается за счет следующих отличительных особенностей инструментального средства «Лакуна»:

  • удобной интерактивной системой создания форм;
  • использования 4GL-языка Visual Script;
  • встроенных возможностей обработки стандартных действий пользователя (удаление, добавление, обновление, печать данных);
  • мощной справочной системы, в подавляющем большинстве случаев не требующей от разработчика написания дополнительного кода;
  • универсального генератора отчетов и других возможностей информационной системы.

«Лакуна» позволяет формировать отчеты практически любой сложности и автоматически по заданной структуре документа поддерживает его отображение на таблицу базы данных и обеспечивает необходимые механизмы манипуляции данными (добавление, обновление, удаление, просмотр), поиск экземпляров документов, печать экземпляров документов и сводных отчетов по нескольким экземплярам.

Для совместимости «Лакуны» с приложениями, спроектированными вне ее, имеется возможность построения структуры документов по готовым таблицам базы данных.

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

Часто используемые элементы алгоритмов могут оформляться в виде хранимых процедур с передаваемыми параметрами. Доступ к таким процедурам возможен из любого приложения, работающего с базой данных, в которой эти процедуры хранятся. Обращение к процедурам допустимо из любого места «Лакуны», где разрешено использование вычисляемых выражений (формул). Именно благодаря возможности написания и хранения пользовательских алгоритмов обработки событий и процедур, дополняющих и расширяющих стандартные операции «Лакуны», разработка каждого следующего приложения может выполняться более эффективно.

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

Система «Лакуна» обеспечивает разграничение доступа к различным элементам приложения и таблицам базы данных при помощи присвоения каждому пользователю имени и соответствующих прав доступа.

«Лакуна» состоит из двух основных систем: системы разработки приложений и системы исполнения приложений (среда run-time).

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

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

Как в системе разработки, так и в системе исполнения приложений имеются два вида подсказки для пользователя: статусные строки и контекстная помощь. Они предопределены для «Лакуны», однако разработчик приложения может настраивать статусные строки и систему контекстной помощи с помощью специальных функций.

«Невод»

«Невод» - инструментальное средство, предназначенное для создания информационно-аналитических систем.

В информационных технологиях принято различать два вида систем: операционные (транзакционные) и информационные (аналитические), то есть системы, ориентированные на операционную обработку данных - системы обработки данных (СОД), и системы, ориентированные на анализ данных - системы поддержки принятия решений (СППР).

«Невод» позволяет быстро создавать и вести системы промежуточного типа (таблица 1).

Применение подобных систем необходимо для ведения учета некоторых объектов, например: физических лиц, юридических лиц, адресов и т.д. Предметную область создает сам администратор системы «Невод» и в качестве объектов учета может выбрать как организованные преступные группировки в случае системы безопасности, так и квартиры в случае риэлторской системы. «Невод» может пригодиться как для учета спортивных событий, команд, игроков, так и для организации электронной газеты объявлений через Internet.

Дело в том, что, работая с «Неводом», пользователь оперирует понятными ему терминами, организованными в виде объектов и их атрибутов, а также связей, в то время как реально данные находятся в реляционных структурах СУБД ЛИНТЕР. Невод позволяет пользователю вводить несколько значений одного атрибута или не заполнять атрибут вообще. Атрибут может быть текстового, целого или вещественного типа, типа даты или мультимедиа, может быть ссылкой на объект или мультигруппой - набором атрибутов. Текстовые атрибуты могут быть словарными, т.е. значения выбираются из справочника (словаря). Справочники поддерживают синонимы, а также иерархию значений.

Введенная информация становится доступной для анализа только после процесса идентификации - сравнения введенных объектов с уже имеющимися в базе. Если введенный объект «похож» на существующий в базе, то в базе не создается новый объект, а недостающая информация дописывается к старому объекту. Правила похожести задает администратор.

Ввод и вывод информации осуществляется в формы, автоматически генерируемые на основе предметной области и редактируемые пользователем. Отчеты создаются на основе тех же универсальных форм в виде файла типа txt, rtf или html. По формам также строятся и простые запросы. Для создания более сложных запросов существует дизайнер запросов, оперирующий терминами предметной области. Запросный режим не ограничен только наложением условий на атрибуты и связи, но и позволяет находить неявные связи между напрямую несвязанными объектами.

Режим работы «Статистика» представляет собой электронную таблицу, в ячейки которой можно выводить результаты работы запросов. Формат обмена информацией через буфер совместим с Excel.

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

Будущее системы

Будущее системы ЛИНТЕР связывается с новой версией СУБД ЛИНТЕР - ЛИНТЕР v.6.0. Эта версия обещает быть более мощной во всех отношениях. Однако, многое из того, что войдет в эту систему уже сделано или будет сделано гораздо раньше. Таким образом, многое из того, о чем ниже идет речь поступит на рынок в релизах ЛИНТЕР v.5.

Большие объемы данных и 64-разрядная арифметика. На данный момент объем информации, хранимой в одной таблице, не может превышать 18 Тбайт. Это определяется тем, что одна таблица не может состоять более чем из 9-ти файлов (3 файла индексов, 3 файла данных и 3 файла больших байтовых объектов), а размер одного файла ограничен размером в 2 Тбайт. Максимальное число записей в одной таблице равно 33554431.

Многие приложения такие данные не устраивают. Сейчас ведутся интенсивные работы как по увеличению числа файлов в одной таблице, так и по использованию больших файлов, более 2 Тбайт (в тех операционных системах, где это возможно). Предполагается, что в ЛИНТЕР v.6.0 эти ограничения будут преодолены.

Мобильность. В ближайшее время планируется перенос ЛИНТЕР на МОС-ЕС (S/390).

Масштабируемость. Здесь основным направлением является разработка многопроцессорного ядра СУБД ЛИНТЕР. Для этого в последних релизах ЛИНТЕР версии 5 был осуществлен переход к стековой организации обработки запроса. Это позволило при декомпозиции запроса порождать подзапросы, обработка которых может выполняться параллельно с другими аналогичными подзапросами, а также с основным запросом. Таким образом, решается проблема распараллеливания обработки не только запросов, выполняющихся по различным каналам, но даже и обработки одного запроса. Кроме этого, возможностями распараллеливания наполнены также и модули более нижнего уровня, например, модули работы с индексами, построения бит векторов и т.д.

Вторым направлением масштабируемости определена зависимость от объема оперативной памяти, особенно при больших объемах (более 256Mбайт). Для увеличения быстродействия (пропорционального росту оперативной памяти) на таких объемах оперативной памяти в СУБД ЛИНТЕР изменены алгоритмы работы с пулом страниц. Опытный образец такой системы уже прошел первые испытания в тестовой лаборатории компании «Релэкс» и показал неплохие результаты.

Производительность (оптимизация, индексы). До настоящего момента основными направлениями развития СУБД ЛИНТЕР были надежность и секретность. Теперь главная задача, стоящая перед разработчиками - увеличение быстродействия системы. В этом направлении планируется включить в СУБД ЛИНТЕР следующие возможности:

1. построение и использование временных индексов при работе с неиндексированными столбцами;

2. индексация с помощью R-деревьев (для ускорения работы с пространственными данными типа карт, выкроек и пр.);

3. использование индексов при некоторых операциях (типа Group By); в некоторых случаях там, где раньше использовалась сортировка, система будет использовать уже готовые упорядоченные структуры B-деревьев;

4. индексация текстовых BLOB-объектов с помощью словных деревьев (для ускорения поиска слов/словосочетаний);

5. оптимизация работы ЛИНТЕР по созданию файлов временных таблиц (образуемых системой при выполнении запросов, включающих предложения Group By и Having); в новых версиях ЛИНТЕР файлы временных таблиц будут создаваться только при недостатке оперативной памяти.

Сетевые компоненты. Уже упоминалось о том, что сетевые компоненты системы отслеживают «живучесть» тех объектов, с которыми они связаны. «Смерть» этих объектов будет вовремя обнаружена, и приложению (или ядру ЛИНТЕР) будет сообщено о невозможности продолжения работы. Однако во многих случаях это не лучший выход. Особенно когда речь идет о высоконадежных системах, где принято неоднократно убедиться в том, что связь с объектом невозможна, несколько раз повторить действие (причем через установленные промежутки времени) и только потом передавать проблему для решения наверх. Именно такой видят сетевую часть СУБД ЛИНТЕР v.6.0 наши специалисты. Возможности настройки сетевых компонент дополнятся также еще одним параметром - тайм-аутом повтора, т.е. промежутком времени, через который будет осуществляться повторение проверки «живучести».

«Горячее» тестирование базы данных. «Горячее» тестирование базы данных (или тестирование физических структур базы в процессе работы СУБД) - еще одна мера повышения надежности СУБД ЛИНТЕР. В следующих версиях ЛИНТЕР язык запросов SQL будет расширен конструкциями тестирования таблиц (указанных в запросе), а также связей между таблицами (проверка ссылок на первичные ключи). Причем таблица может тестироваться не только целиком, но и частично (по условиям на данные). Это позволит, например, тестировать не весь индекс (что может быть очень длительным процессом), но только ту его часть, где расположены указанные (в предложении WHERE) данные. Тестирование может иметь самый низший приоритет и, следовательно, выполняться в фоновом режиме, т.е. только тогда, когда нет других, более приоритетных запросов.

Архиватор

1. Переход к использованию языка BSL (Backup Script Language) описания сценариев архивации. BSL является достаточно развитым средством по управлению реакцией на наступление некоторых событий как регулярных (например, - вечером каждой пятницы), так и специальных (например, превышение критического времени бездействия пользователей или превышение объема сделанных в базе данных изменений).

2. Утилита архивирования lhb будет разделена на три части.

  • Сервер. Часть ядра СУБД ЛИНТЕР, отвечающая за формирование архивных блоков данных.
  • Клиент-демон (службы). Собственно заказчик и получатель данных, который формирует запросы к серверу и создает файл. Физически может находиться как на клиентской машине, так и на любой другой.
  • Клиент-монитор. Осуществляет общее управление и контроль над процессами сохранения восстановления. Является инструментом для конечного пользователя.

3. Добавление в lhb функций сохранения данных в псевдотекстовом формате и формирование блоков базы данных при восстановлении (быстрая загрузка) для обеспечения переноса между версиями.

Реальное время. В ближайшее время добавится еще одно средство реального времени - тайм-ауты блокировок. Допустимым временем ожидания блокировки можно будет управлять из приложения пользователя.

Транзакционные режимы ЛИНТЕР

1. Переход к многоверсионности данных. При этом каждый пользователь может «видеть» базу данных со своими изменениями и не видеть чужих.

При наличии многоверсионности можно «накрыть» все уровни изолированности, описанные в стандарте SQL92 Entry - Entry Level спецификация Международной Организации по Стандартизации (ISO) 9075-1992 языка баз данных SQL или сокращенно SQL92E (Спецификация Американского национального института стандартов (ANSI) X3.135-1992 идентична спецификации ISO).

Расширение реализации плоских транзакций с точками синхронизации (savepoint).

2. Расширение реализации плоских транзакций с точками синхронизации (savepoint).

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

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

3. Переход к дереву транзакций.

Иерархические транзакции ЛИНТЕР будут упорядочены по стратегиям обработки (Optimistic, Pessimistic, Autocommit, Read-only) и по уровням изолированности (кроме уровней ISO вводятся дополнительные). Для каждой стратегии реализуется несколько уровней изолированности. Снимается ограничение двухуровневой иерархии для приложений пользователя. При обработке хранимых процедур и триггеров это ограничение уже снято. Такой протокол обработки транзакций позволит существенно снизить количество конфликтов, что особенно важно для систем OLAP.

Развитие механизмов распределенности. Настоящий механизм распределенности в СУБД ЛИНТЕР недостаточно эффективен из-за синхронного использования запросов к удаленному серверу как в loltp, так и ядре ЛИНТЕР. В ЛИНТЕР v.6.0 эта ситуация будет исправлена, как ядро, так и loltp будут использовать только асинхронный интерфейс обмена - запрос-ответ.

ЛИНТЕР v.6.0 станет более интеллектуальной системой при оптимизации распределенных запросов. В особенности это касается запросов, где возможно появление промежуточных временных таблиц и индексов.

 

Таблица 1. Сравнительные характеристики информационных систем
Характе-

ристика
Опера-

ционные
Аналитичес-кие Невод
Частота обновле-ния Высокая частота, маленькими порциями Малая частота, большими порциями Средняя частота, средними порциями
Источ-ники данных В основном, внутренние В основном, внешние В основном, внутренние
Объемы хранимых данных Сотни мегабайт, гигабайты Гигабайты и терабайты Гигабайты
Возраст данных От месяца до года От несколь-ких лет до десят-ков лет Несколько лет
Назна-чение Оперативный поиск и преобразова-ние данных Хранение истори-ческих данных, аналити-ческая обработка, прогнози-рование. Хранение, поиск, аналити-ческая обработка

Литература

1. ИНТЕРЕАЛ - мобильная СУБД с интерфейсом реляционного типа /И.А. Бойченко, С.П. Маркин, А.В. Пешков и др. // Прикл. Информатика. - 1989. - Вып.15. - с. 49-71,
2. Состояние и направление развития СУБД с интерфейсом реляционного типа ИНТЕРЕАЛ в системах обработки и использования информации /И.М. Аберемков, И.А. Бойченко, А.В. Пешков, Н.И. Федченко // УСиМ - 1990 - №4 - 1990 - С. 48-54
3. Возможности мобильной СУБД ЛИНТЕР на рынке пользователей ПЭВМ /И.А. Бойченко, Ф.М. Мучник, А.В. Пешков // УСим - 1992 - №3-4 - С. 124-127

Виталий Максимов (vitamax@relex.ru), Л. Козленко, С. Маркин, И. Бойченко – компания РЕЛЭКС (Воронеж).