А.Брюзгин
Интерфейс Лтд, тел.: 135-55-00


Общие характеристики
Платформы
Сетевые протоколы
Объекты
Курсоры
Программный интерфейс
Оптимизация и выбор плана выполнения запроса
Стоимостная модель оптимизации
Управление статистикой базы данных
Хранимые процедуры
Триггеры
Внешние функции хранимых процедур
Аудит

За последние годы технология клиент-сервер стала темой номер один в компьютерном мире. Наиболее яркими представителями технологии клиент-сервер являются многопользовательские реляционные СУБД. Эта статья посвящена одному из представителей сегодняшней технологии клиент-сервер - реляционной СУБД SQLBase фирмы Gupta.

Общие характеристики

SQLBase - это реляционная многопользовательская СУБД фирмы Gupta, выполненная в архитектуре клиент-сервер. Она предназначена для использования в качестве сервера баз данных в локальных вычислительных сетях на базе персональных компьютеров. SQLBase ориентирована, прежде всего, на сети масштаба малого и среднего предприятия с количеством одновременно работающих с СУБД рабочих станций от 20 до 100, а также на подразделения (филиалы, отделения) крупных организаций. В целом СУБД такого класса называют серверами для рабочих групп (Workgroup Server).

Сервер SQLBase может работать с базами данных, расположенными на одном компьютере, но позволяет располагать и распределять их на разных физических и логических дисках и других носителях (оптические накопител и CD-ROM).

Режим работы SQLBase, параметры размещения его баз данных, а также описание сетевых протоколов сервера содержатся в конфигурационном файле SQL.INI, который имеет структуру стандартного INI-файла системы Windows. SQL.INI является универсальным файлом конфигурации для всех продуктов Gupta и включает в себя секции, описывающие поведение различных серверов и клиентов Gupta.

Платформы

SQLBase разрабатывалась специально для применения на персональных компьютерах с процессорами фирмы Intel. В настоящее время эта СУБД выпускается для следующих операционных систем: Novell NetWare 3.x и 4.x, Windows 95 и NT, OS/2 2.x. Существует также локальная версия для платформы Windows 3.x. При работе в Windows 95, Windows NT и OS/2 SQLBase поддерживает как традиционную технологию клиент-сервер, так и технологию клиент-клиент, позволяющую создавать системы серверов баз данных с распределением данных и задач между компьютерами даже в одноранговой сети.

Сетевые протоколы

SQLBase осуществляет поддержку практически всех распространенных сетевых протоколов, включая IPX/SPX для NetWare, NetBIOS, NetBEUI, Named Pipes и TCP/IP (Windows Sockets) для Windows NT и OS/2. Для Windows 95 и Windows NT фирма Gupta разработала 32-разрядный протокол обмена данными Anonimous Pipes для работы с локальным сервером SQLBase в этих средах. Кроме этого, SQLBase поддерживает технологию SNMP, что позволяет управлять сервером баз данных в сложных сетях, работающих под управлением Novell NetWare.

SQLBase поддерживает стандартный ODBC-интерфейс для связи с базами данных в среде Windows. Драйвер ODBC входит в комплект сервера SQLBase.

Объекты*)

SQLBase содержит набор стандартных объектов и структур, общих для большинства реляционных СУБД. Данные SQLBase хранит в виде таблиц, состоящих из колонок и строк. SQLBase поддерживает представления (views) и рассматривает их как отдельные объекты базы данных. Для поддержания уникальности данных в колонках таблиц, а также для ускорения доступа к данным используются индексы. База данных SQLBase также хранит информацию о пользователях и их привилегиях. В качестве расширения стандартного набора объектов SQLBase содержит триггеры, хранимые команды и хранимые процедуры. Типы данных, поддерживаемые SQLBase, приведены на Рис. 1. Следует отметить, что тип данных CHAR в SQLBase не отличается от VARCHAR (в обоих случаях СУБД не хранит пустые места в колонках) и поддерживается, в основном, для совместимости с DB2.

Типы Данных

Описание

Размерность

Примечание

CHAR (или VARCHAR) Строковой тип

до 254 байт

Имеет вид CHAR(3). Пустые места для хранения
LONG VARCHAR Строковой тип Неограниченный размер Для этого типа не поддерживаются предложения WHERE, ORDER BY и многие функции СУБД.
NUMBER Числовой тип

до 15 цифр

Суперсет всех числовых типов SQLBase.
DECIMAL Числовой тип с фиксированной точкой

до 15 цифр

Имеет вид DECINAL (размер десятичных знаков). SQLBase не поддерживает тип CORRENCY. Используйте для этого DECIMAL (15,2 ).
INTEGER Числовой целый тип

до 10 цифр

SMALLINT Числовой целый тип

до 5 цифр

DOUBLE PRECISION Для чисел с плавающей точкой.
FLOAT Числовой тип

до 15 цифр

Отличается от DOUBLE PRECISION указанием количества значащих цифр.
DATATIME (или TIMESTAMP ) Дата/Время Точность временной компоненты до 1 мксек.
DATE Дата

TIME Время Точность до 1 сек.

Рисунок 1.
Типы данных SQLBase.

SQLBase поддерживает стандарт SQL-89 с некоторыми расширениями. Кроме поддержки выполнения стандартных SQL запросов, SQLBase содержит большое количество встроенных функций (более 60). Они включают агрегатные функции, функции преобразования форматов данных, выбора и логического ветвления, обработки строковых, числовых и временных данных, а также различные математические и финансовые функции.

В SQLBase существуют пользователи трех уровней: CONNECT, RESOURCE и DBA. Особенности уровня доступа к данным и другие привилегии каждой категории пользователей приведены на Рис. 2.

Тип Показателя

                  Описание

SYSADM Создает пользователей и устанавливает их пороли и права доступа.
DBA Выдает, изменяет и отнимает права доступа к объекту БД для любого пользователя.
RESOURCE Создает и удаляет объекты БД. Выдает, изменяет и отнимает права доступа к этим объектам для других пользователей.
CONNECT Имеет доступ к объектам, но не может их создавать.

Рисунок 2.
Типы пользователей SQLBase

Всю информацию о базе данных сервер хранит в системном каталоге базы. При этом поддерживаются два системных каталога: один полный, который содержит всю информацию об объектах и состоянии базы данных SQLBase, и универсальный, который совместим по структуре с системными каталогами большинства других СУБД. Поддержка универсального системного каталога позволяет управлять базами данных SQLBase из программ и средств администрирования СУБД других фирм. Краткое описание таблиц системного каталога приведено на Рис. 3.

Тавлица

          Описание

SYSCOLAUTH Права обновления колонок.
SYSCOLUMNS Колонки базы данных.
SYSCOMMANDS Хранимые команды и хранимые процедуры.
SYSEVENT Системные события таймера ( в текущей версии не используются).
SYSEXECUTEAUTH Права выполнения хранимых процедур.
SYSFKCONSTRAINT Внешние ключи ( foreign key ).
SYSINDEXER Индексы.
SYSKEYS Колонки индексов.
SYSPARTTRANS Незавершенные распределенные транзакции.
SYSPKCONSTRAINTS Первичные ключи ( primary key ).
SYSROWIDLISTS Сохраненнные множества результатов ( result sets ).
SYSYNONYMS Синонимы объектов баз данных.
SYSTABAUTH Права доступа к таблицам.
SYSTABCONSTRAINTS Ограничения ссылочной целостности.
SYSTABLES Таблицы и views.
SYSTRGCOLS Колонки триггеров.
SYSTRIGGERS Триггеры.
SYSUSERAUTH Пользователи БД и их пароли.
SYSVIEWS Описание views в виде SQL запросов.

Рисунок 3.
Таблицы системного каталога SQLBase.

Курсоры

Сеанс работы с базой данных инициируется клиентом с помощью команды CONNECT и прекращается командой DISCONNECT. Во время сеанса клиент выполняет одну или несколько транзакций к базе данных.

Курсор в SQLBase имеет много самых разных значений. Прежде всего, курсор - это идентификатор контакта пользователя с базой данных (или контакта администратора с сервером SQLBase). Далее, с курсором связаны скомпилированные запросы на языке SQL, извлеченные из базы данных и подготовленные к выполнению хранимые команды и процедуры, а также полученные в результате выполнения запросов, команд и процедур результирующие множества (result sets). Наконец, курсор также определяет положение (строку) в текущем результирующем множестве (result set), обрабатываемым клиентским приложением.

В SQLBase не существует специальной команды, определяющей начало транзакции, подобной BEGIN WORK или BEGIN TRANSACTION. Транзакция автоматически начинается с первого запроса к базе данных, последовавшего за окончанием предыдущей транзакции. Для указания окончания транзакции служат команды, приведенные на Рис. 4.

Команда

                      Описание

ROLLBACK Неудачное окончание транзакции. Изменения не записываются в базу данных. Блокировки, связанные с данной транзакцией, сбрасываются.
COMMIT Удачное окончание транзакции. Изменения записываются в базу данных. Блокировки, связанные с данной транзакцией, сбрасываются.
SAVEPOINT Удачное окончание части длительной транзикции. Частичные изменения записываются в базу данных. Эта команда используется во время длительной транзакции ( например, ввода большого количества данных ) для фиксации прохождения некоторого этапа. Если при обработке транзакции произойдет ее откат ( ROLLBACK ), все изменения, сделанные до последней команды SAVEPOINT останутся в базе данных.

Рисунок 4.
Команды окончания транзакции SQLBase.

SQLBase поддерживает именованные и распределенные транзакции. Именованные транзакции позволяют объединять несколько курсоров от одного клиента в процесс, изолированный от других процессов в той же базе данных. Это позволяет организовать работу клиента с базой одновременно в нескольких режимах. Например, клиент может выделить в своем приложении две именованные транзакции - "Проводка" и "Баланс". При этом ошибка выполнения запроса по одному из курсоров транзакции "Проводка" приведет к откату только этой транзакции и не окажет никакого действия на курсоры транзакции "Баланс".

Описание распределенных курсоров приведено ниже в разделе "Распределенные базы данных". Существует также разделение курсоров по объекту контакта.

Курсоры базы данных используются для выполнения запросов к базе данных (предложений SELECT, INSERT, UPDATE, DELETE), а также выполнения команд конфигурирования базы данных (CREATE, ALTER, DROP, GRANT, REVOKE и т.д.).

Курсоры сервера применяются для операций, непосредственно связанных с функционированием сервера SQLBase. К ним относятся процедуры архивирования и восстановления (BACKUP и RESTORE), команды создания, активизации и удаления баз данных (CREATE DATABASE, DROP DATABASE, INSTALL DATABASE, DEINSTALL DATABASE), а также команды, изменяющие параметры и режимы работы SQLBase в целом.

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

Программный интерфейс

Основным программным интерфейсом SQLBase является SQL API - библиотека функций на языке C, реализующая все возможности управления СУБД. Помимо базового интерфейса SQL API существует большое количество программ и библиотек, реализующих собственные интерфейсы к SQLBase. Среди них нужно прежде всего отметить SQLBase++ (библиотеку классов в стандарте MFC), Borland Delphi и целый ряд языков и систем IV поколения, включающих SQLWindows (Gupta), PowerBuilder (PowerSoft), Crystal Reports и Crystal Info.

Оптимизация и выбор плана выполнения запроса

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

Результатом работы оптимизатора SQLBase является план выполнения запроса (execution plan). Говоря упрощенно, execution plan - это последовательность шагов, которая указывает программе-серверу SQLBase, как выполнить запрос. В плане каждый шаг может быть однотабличным (single table) или двухтабличным (two table). Все шаги производят результирующие таблицы (result tables). Результирующая таблица не обязательно должна иметь материальное воплощение в виде хранимого объекта. Для любого шага плана результирующая таблица может быть пользовательской (user-defined), временной (teporary) или концептуальной (conceptual).

Однотабличный шаг плана

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

  • Последовательное сканирование (Sequental Scan) - это наиболее простой из всех методов доступа. В этом методе считывается каждая страница данных, принадлежащая исходной таблице. (Следует отметить, что все страницы базы данных для этой таблицы связаны между собой, поэтому не требуется сканирование всего файла базы данных.)
  • Доступ по индексу (Index Access). Существуют два способа использования индекса. При первом - значение индекса известно и он может быть использован для позиционирования на индексной странице БД и последующего извлечения данных непосредственно из индексной страницы. При втором способе индексные страницы сканируются в возрастающем или убывающем порядке для поиска положения индекса. Если запрос включает колонки таблицы, не входящие в индекс, потребуются дополнительные операции для считывания информации из страниц данных таблицы.
  • Хэшированный доступ (Hash Access). В этом методе ключевое значение используется для прямого извлечения информации из страницы данных, которая содержит строки, удовлетворяющие значению ключа. Метод преобразования ключа в адрес страницы, на которой он находится, носит название "хэширование". Хэшированный доступ может быть использован только в том случае, если для ключа создан хэшированный индекс и предикатом является равенство "=".

Двухтабличный шаг плана

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

  • Вложенный цикл (Nested loop) и его вариации.
  • Слияние индексов (Index merge).
  • Гибридное хэшированное объединение (Hybrid hashed join).

Пример схемы выполнения

В качестве примера рассмотрим базу данных типа поставщик-товар-поставка. База содержит 3 таблицы: S для поставщика, P для товара и SP для поставок. Таблица S имеет уникальный первичный ключ S#. Таблица P имеет уникальный первичный ключ P#. Таблица SP имеет уникальный первичный ключ на колонках S#P#. Дополнительно эта таблица содержит индексы для колонок City, Color и Weight. Схема базы приведена на Рис. 5.

Таблицы

Колонки

Индексы

S

S#, SName, Status, City SXS#(S#), SXCITY(City)

P

P#, PName, Color, Weight, City PXP#(P#), PXCOLOR(Color), PXWEIGHT(Weight)

SP

S#, P#, QTY SPXS#P#(S#, P#)
Запрос 1: Select * from P where color = "Red" and weight =19;
Номер шага Внешняя таблица Внешний индекс Внутренняя таблица Внутренний индекс Результатирующая таблица Метод объединения

1

P

PXWEIGHT

RESULT

Рисунок 5.
Схема демонстрационной базы данных.

Для выполнения данного запроса у оптимизатора есть три варианта: 1) последовательное сканирование, 2) индексный доступ с помощью индекса PXCOLOR и 3) индексный доступ с помощью индекса PXWEIGHT. В данном случае оптимизатор выбрал индекс PXWEIGHT. Поэтому программа сервера будет использовать ключ weight (значение 19) для извлечения всех строк, которые удовлетворяют условию "weight =19", и отфильтровывать те из них, которые не удовлетворяют второму условию (color = "Red"). Оптимизатор предпочел индекс PXWEIGHT индексу PXCOLOR, поскольку он посчитал, что в таблице существует меньше строк, удовлетворяющих критерию выбора по ключу weight. Иными словами, индекс PXCOLOR является более "плохим" и потребует больше операций ввода/вывода и команд процессора для выполнения запроса. Результат запроса представляется в виде концептуальной таблицы RESULT.

Стоимостная модель оптимизации

Оптимизатор SQLBase использует так называемый стоимостной метод (cost-based technique) для определения наилучшего плана выполнения запроса, в отличие от методов, основанных на анализе синтаксиса (syntax-based) запроса или жестко установленных правилах выбора (rule-based). Оптимизатор оценивает стоимость или затраты на работу процессора и операции ввода/вывода для различных методов доступа к данным и операций над ними. Стоимость процессора оценивается в миллисекундах. Стоимость ввода/вывода, которая представляет собой количество операций ввода/вывода в секунду, также преобразуется в миллисекунды. Такой подход позволяет проводить сравнение нагрузки на процессор и подсистему ввода/вывода. Производительность методов доступа к данным и операций объединения зависит от размера и распределения данных. Информация о данных представлена в виде статистики таблиц и индексов. Запрос разбивается на ряд небольших индивидуальных шагов. Наименьший шаг - это доступ к данным одной таблицы, который выбирается из всех возможных методов доступа. При этом исследуются все возможности выбора данных из таблицы, а также методы объединения между любыми двумя таблицами или таблицей и промежуточным результатом. Оптимизатор выбирает наиболее простой и эффективный план выполнения.

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

  • Операции сравнения;
  • Перемещение данных;
  • Повторный доступ к той же таблице;
  • Методы объединения данных;
  • Использование буферов ввода/вывода;
  • Распределение предикатов.

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

Управление статистикой базы данных

Управление статистикой базы данных в SQLBase служит следующим целям:

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

Следует отметить, что существующий метод воздействия на выполнение SQL-запросов с помощью команды UPDATE STATISTICS является очень сложным и весьма нелинейным.

Хранимые процедуры

Хранимые процедуры (stored procedures) представляют собой приложения, которые хранятся в базе данных. Обычно в среде клиент-сервер конечные приложения располагаются на клиентской машине и там же выполняются. Любой доступ к базе данных из конечного приложения использует контакт с сервером по компьютерной сети. Когда же приложение располагается внутри базы данных, оно называется хранимой процедурой. Хранимые процедуры выполняются непосредственно на компьютере сервера базы данных.

SQLBase использует хранимые процедуры, написанные на языке инструмента разработки конечных приложений SQLWindows Application Language (SAL). Использование хранимых процедур преследует следующие цели.

  • Повышение производительности. Так как прикладная программа перенесена на сервер, она не требует затрат на передачу информации по сети при обращении к базе данных. Кроме того, сервер обычно бывает более мощным компьютером, чем клиентские машины. Следовательно, те же операции выполняются на сервере быстрее.
  • Простота использования. Обычно технология клиент-сервер подразумевает большое количество клиентов, подключенных к одному серверу. Использование хранимых процедур позволяет хранить приложение на одном компьютере, а не на каждом клиенте в отдельности. Если приложение в базе данных модифицируется, оно становится сразу доступно всем клиентам в наиболее обновленном виде.
  • Усиление защиты данных. Пользователь может получить возможность доступа к данным только через использование заранее запрограммированных процедур и не иметь прямой возможности изменять данные. Следовательно, набор операций, которые могут быть осуществлены пользователем, легко контролируются с помощью управления доступом к небольшому числу хранимых процедур.
  • Ускорение процесса освоения. Хранимые процедуры SQLBase пишутся на языке SAL. Кроме того, разработчики могут создавать и отлаживать прототипы хранимых процедур в среде SQLWindows и затем переносить их в базу данных с помощью программы SQLConsole.

В SQLBase имеется возможность хранения двух типов процедур.

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

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

Доступ пользователей к хранимым процедурам

Для того чтобы выполнить хранимую процедуру, пользователь должен обладать определенными привилегиями. Он может иметь право выполнить процедуру либо с привилегиями автора (execute with creator privilege), либо со своими привилегиями (execute with grantee privilege). Если пользователь выполняет процедуру с правами автора, он получает все его права по отношению к объектам базы данных на время выполнения процедуры. При втором способе выполнения изменения прав пользователя не происходит. Использование возможности расширения (изменения) прав пользователя на время выполнения хранимой процедуры позволяет повысить защищенность данных и канализировать доступ к ним через отработанные и проверенные процедуры.

Получение кодов ошибок из хранимых процедур

Процедура указывает на нормальное завершение, возвращая нулевое значение в вызвавшее ее приложение.

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

Пример хранимой процедуры

Ниже приведен пример хранимой процедуры SQLBase, иллюстрирующей некоторые моменты, описанные в данной статье. Эта процедура обновляет баланс по счету AccountNum в соответствии с выплаченной суммой nAmount и возвращает новое значение баланса в переменной nNewBalance. Если при этой операции происходит овердрафт, процедура устанавливает флаг bOverDrawn.

Procedure Withdraw 
Parameters 
Number: nAccount 
Number: nAmount 
Receive Number: nNewBalance 
Receive Boolean: nOverDrawn 
Local Variables 
Sql Handle: hSelect 
Sql Handle: hUpdate 
String: sSelect 
String: sUpdate 
Number: nStatus 
Actions 
On Procedure Startup 
Set sSelect = "Select Balance from Checking where AccountNum=:nAccount" ||
"into :nNewBalance" 
Set sUpdate = "Update Checking Set Balance = Balance - :nAmount" || "where AccountNum = :nAccount" 
Call SqlConnect( hSelect ) 
Call SqlPrepare( hSelect, sSelect ) 
Call SqlConnect( hUpdate ) 
Call SqlPrepare( hUpdate, sUpdate ) 
On Procedure Execute 
Call SqlExecute( hSelect ) 
Call SqlFetchNext (hSelect, nStatus ) 
Set nNewBalance = nNewBalance - nAmount 
If ( nNewBalance < 0 ) 
Set bOverDrawn = TRUE 
Else 
Set bOverDrawn = FALSE 
Call SqlExecute( hSelect ) 
On Procedure Close 
Call SqlDisconnect( hSelect ) 
Call SqlDisconnect( hUpdate ) 

Триггеры

Триггеры - это определяемые пользователем действия, которые выполняются, когда над таблицей и к которой прикреплен триггер, выполняются операции INSERT, UPDATE или DELETE. В SQLBase действия триггера являются хранимыми процедурами. Иными словами, пользователь создает хранимые процедуры, которые описывают действия, совершаемые триггерами. В SQLBase триггеры используются для решения трех основных задач.

  • Усиление ссылочной целостности. Триггеры могут быть использованы для реализации ограничений ссылочной целостности, выходящей за пределы стандартных ограничений SQLBase. Например, пользователь может захотеть реализовать правило каскадного изменения данных (update cascade rule). Он может это сделать, создав триггер, который будет обновлять дочернюю таблицу (таблицы) при каждом изменении колонки в родительской таблице.
  • Проверка данных. Триггеры могут выполнять разнообразную проверку данных. Значения колонок могут передаваться в триггерные процедуры в качестве параметров, где над ними могут производиться самые разнообразные операции. В текущей версии SQLBase реализован механизм, который позволяет производить ввод данных в таблицы непосредственно из триггера, без передачи информации извне. Например, пользователь может создать триггер, который будет получать из приложения данные для ввода в строку таблицы, создавать уникальный ключ для этой строки внутри своей процедуры и передавать в базу данных полную строку с ключом. Помимо генерации ключей триггеры SQLBase могут выполнять и другие подобные операции.
  • Регистрация изменения данных. Создатель таблицы или администратор базы данных может пожелать иметь информацию о времени каждого изменения данных в таблице, а также о том, какой пользователь эти изменения производил. Для этого он создает триггер, в который поступает системное время операции UPDATE и имя пользователя. Процедура триггера затем вводит эту информацию в специальную таблицу регистрации изменений. Использование триггеров подобного типа позволяет организовать системы регистрации изменений, не зависящие от действий пользователя и поэтому наиболее надежные при попытках выполнения несанкционированных операций.

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

Триггер может быть определен для выполнения либо перед операцией insert/update/delete (before триггер), либо после нее (after-триггер). Типичный пример использования before-триггеров - проверка данных. After-триггеры полезны в тех случаях, когда хранимая процедура триггера содержит код, анализирующий содержимое таблицы, на которой определен триггер, и этот код должен включать результаты последней операции insert/update/delete.

Операции insert/update/delete, которые содержат предложения WHERE или субзапросы (sub-selects), модифицируют более одной строки таблицы. Триггеры SQLBase могут быть сконфигурированы таким образом, чтобы запускаться только один раз за всю операцию или каждый раз при изменении отдельной строки.

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

При передаче данных в процедуры триггеров можно использовать следующие типы данных в качестве параметров процедур.

  • Значения колонок таблицы. Поскольку триггер определяется на конкретной таблице базы данных, он "знает" о ее строении: количестве, именах и типах колонок и т.д. Поэтому значения колонок таблицы могут передаваться в процедуру непосредственно по своим именам.
  • Константы. Псевдо-константы. В процедуру можно передавать некоторые ключевые слова SQLBase, например: USER, SYSTIME и другие.

Если в процессе выполнения операции UPDATE содержимое колонки изменяется, имеется возможность передать в процедуру триггера как старое, так и новое значение колонки. Для этого служит предложение REFERENCING в определении триггера. Если предложение REFERENCING не используется, по умолчанию значение колонки является старым для before update-триггеров и новым для after update-триггеров. Поскольку для insert-триггеров старых значений не существует, значение колонки по умолчанию является новым. Аналогично значение колонки для delete-триггера является старым.

Пример триггера

Ниже приведен пример триггера, который реагирует на обновление колонки в таблице. Предположим, мы имеем таблицу T1, содержащую целочисленную колонку C1 и таблицу T2 с колонками (OldC1 int, NewC1 int, Updater char(10)). В триггер передаются старое и новое значение колонки C1 и имя пользователя. Триггер затем вводит эту информацию в таблицу T2. (Отметим возможность определения хранимой процедуры триггера непосредственно в теле триггера с помощью оператора INLINE.)

create trigger tg1 before update of c1 on t1 
referencing old as o new as n 
(execute inline (o.c1, n.c1, user) 
procedure p1 static 
parameters 
number: old 
number: new 
string: updater 
actions call sqlimmediate( "insert into t2 values (:old, :new,:updater)" 
) 
for each row; 

Внешние функции хранимых процедур

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

  • Перенос процедурной логики в базу данных для распределенного использования многими приложениями.
  • Улучшение производительности путем объединения большого количества запросов к базе данных в один вызов сервера.

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

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

1. Создание механизма, позволяющего пользователям самим расширять функциональность хранимых процедур на основе концепции plag & play с применением стандартных компонентов или пользовательских программ.

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

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

Внешняя функция - это любая пользовательская функция, которая располагается в отдельной библотеке (Dynamic Link Library или DLL для платформы Windows) и может быть динамически вызвана для выполнения из другой задачи. Функция может быть написана на любом языке, допускающем создание DLL. Единственным ограничением является требование использования в качестве параметров типов переменных, поддерживаемых SQLBase, и следование требованиям программного интерфейса.

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

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

Применение внешних функций дает пользователям SQLBase следующие преимущества:

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

Внешняя функция является новым объектом схемы базы данных SQLBase. Она создается с помощью команды CREATE EXTERNAL FUNCTION. Имя функции, ее физическое положение и интерфейс (параметры и их типы данных, возвращаемые данные и пр.) передаются в этой команде. Данная информация хранится в системном каталоге в специальных таблицах. Ниже приведен пример описания внешней функции.

CREATE EXTERNAL FUNCTION MyFunc 
PARAMETERS (Number: INT) 
RETURNS (BOOLEAN: WORD) 
DESCRIPTION "Sample External Function Declaration" 
LIBRARY MYLIB.DLL 
EXPORT ORDINAL 2 
EXECUTE IN SAME THREAD 

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

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

Области применения внешних функций

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

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

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

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

Другим классом внешних функций могут быть генераторы отчетов в режиме off-line. При этом вместо запуска приложения отчетов с клиентской машины весь модуль (или набор функций) может быть создан в виде динамической библиотеки, которая вызывается из хранимой процедуры как внешняя функция. Код этой функции может осуществлять контакт с базой данных и извлекать нужные для генерации отчета данные. Основным преимуществом такого подхода является повышение производительности, поскольку весь код будет выполняться на сервере без передачи данных и команд по сети.

Аудит

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

  • Мониторинг активности сервера баз данных - регистрация разнообразной информации на регулярной основе.
  • Дополнительные возможности защиты данных. Предыдущие версии SQLBase осуществляли защиту данных на уровне имени и пароля пользователя, однако не регистрировали попытки нарушить систему защиты. Аудит позволяет регистрировать такие случаи, как попытки доступа к базе данных с неправильным именем или паролем. Кроме того, есть возможность регистрировать попытки нарушения пользователем его привилегий по отношению к объектам базы данных, например попытки считать информацию из закрытых для него таблиц.
  • Отладка приложений. Можно использовать аудит для отладки конечных приложений путем просмотра того, какие действия приложение осуществляет по отношению к базе данных и серверу.
  • Повышение производительности базы данных. Аудит базы данных позволяет получить информацию обо всех SQL-запросах и транзакциях. Это свойство можно использовать непосредственно на рабочем месте пользователя для решения проблем типа "Я нажимаю вот эту кнопку и потом жду 20 минут выполнения запроса". Поскольку аудит предоставляет временную информацию о выполнении запросов, его можно использовать для анализа причин снижения производительности конечных приложений.

Существует два класса аудита: глобальный аудит и аудит производительности. В свою очередь, каждый из классов состоит из нескольких категорий, описание этих категорий приведено на Рис. 6.

Класс

Категория

                  Описание

Global

Rejected logons Регистрирует неудавшиеся попытки контакта с базой данных. Используется для идентификации пользователей, которые пытаются получить доступ к закрытым базам данных.
Security violations Регистрирует пользователей, пытающихся получить доступ к данным не имея соответствующих привелегий.
Valid logons/logoffs Регистрирует все удавшиеся события соединения и отсоединения. Используется для регистрации сеансов работы пользователя с системой.
Valid connects/disconnects Регистрирует все команды CONNECT и DISCONNECT.
Database create, drop, install and deinstalls Регистрирует выполнение операции CREATE, DATABASE, DROP DATABASE, INSTALL DATABASE & DEINSTALL DATABASE.
Backup & restore operations Регистрирует все операции BACKUP и RESTORE
Database deadlock & timeout Записывает информацию о всех событиях deadlock и timeout. Очень важная категория, которая может быть использована для разрешения проблем блокировки.
Table access information Регистрирует информацию о том, кто реализует доступ к таблицам базы данных.
Table update information Регистрирует информацию о том, кто выполняет операции insert/update/delete по отношению к таблицам базы данных.
Performance Connects and disconnects Регистрирует время выполнения каждой операции connect/disconnect.
SQL command compilation, execution, storage and retrieval Эта категория регистрирует информацию о времени компиляции и выполнения запроса, записи и извлечения хранимой информации.
End of transaction Регистрирует длительность каждой транзакции. Может использоваться для выявления долго идущих транзакций, которые могут являться источниками deadlock и timeout.

Рисунок 6.

Информация аудита записывается в файл аудита. Файл аудита является плоским текстовым файлом. Его содержимое можно просматривать из программы SQLConsole или в любом текстовом редакторе.


*) В этой статье термин "объект" не связан с традиционным понятием объекта, принятом в объектно-ориентированном программировании - прим.ред.