
- •Глава 1. Изучение Системы управления базами данных и приложения субд.
- •1.1. Разработка клиентских приложений.
- •Классификация средств разработки приложений.
- •2.1.Классификация приложений.
- •2.2.Средства разработки, ориентированные на конкретные субд.
- •2.3.Средства разработки, универсальные по отношению к субд
- •2.4.Приложения в архитектуре "клиент-сервер"
- •2.5.Распределенные приложения
- •2.6.Разработка успешных приложений для субд Oracle
- •Влияние стандартов
- •Функциональные возможности
- •Заключение
Влияние стандартов
Если все СУБД соответствуют стандарту SQL92, они должны быть одинаковыми. По крайней мере, такое предположение делалось неоднократно.
SQL92 – стандарт ANSI/ISO для СУБД. Он является преемником стандарта SQL89. Стандарт определяет язык (SQL) и поведение (транзакции, уровни изоляции и т.д.), которые определяют поведение СУБД. Знаете ли вы, сколько СУБД, доступных коммерчески, соответствуют стандарту SQL92? Знаете ли вы, что это мало что означает в вопросах мобильности запросов и приложений?
Начиная знакомство со стандартом SQL92, мы обнаружим, что стандарт имеет четыре уровня:
начальный уровень (Entry-level) – уровень, который реализован большинством производителей СУБД. Имеет небольшие усовершенствования по сравнению с предыдущим стандартом SQL89. Никто из производителей СУБД не имеет сертификатов более высокого уровня; фактически, Национальный институт стандартов и технологий (NIST, National Institute of Standards and Technology), ответственный за сертификацию на соответствие стандарту, даже не проводил никакой сертификации на соответствие более высоким уровням стандарта. Рабочая группа, которая в 1993 году занималась сертификацией СУБД Oracle 7.0 на соответствие начальному уровню стандарта SQL92. Набор функциональных возможностей СУБД Oracle 7.0 соответствует начальному уровню стандарта;
переходный (Transitional) – функциональные возможности этого уровня находятся где-то между возможностями начального уровня и промежуточного;
промежуточный (Intermediate) – добавлено много функциональных возможностей включая (приведен неполный список возможностей):
динамический SQL,
каскадные операции удаления (DELETE), обеспечивающие сохранение ссылочной целостности,
типы данных DATE (дата) и TIME (время),
домены,
символьные строки переменной длины,
выражения CASE (оператор выбора),
функции CAST (функции приведения типов данных),
полный (Full) – добавлены средства обеспечения (список возможностей также неполный):
управления соединениями,
строкового типа данных BIT (бит),
откладываемых ограничений целостности (Deferrable integrity constraints),
производных таблиц в предложениях FROM,
подзапросов в предложениях CHECK,
временных таблиц.
В начальный уровень стандарта не включены такие функциональные возможности, как внешние соединения, новый синтаксис внутренних соединений и т.д. В переходном уровне специфицирован синтаксис внешних и внутренних соединений. В промежуточном уровне появились дополнительные функциональные возможности, а в полный уровень, естественно, вошел весь стандарт SQL92. В большинстве книг о стандарте SQL92 не рассматриваются различия между этими уровнями, что приводит к путанице. В таких книгах демонстрируется теоретическая реализация СУБД в соответствии с полным уровнем стандарта SQL92, что делает невозможным их практическое применение в каких-либо СУБД, соответствующих стандарту SQL92. Например, в СУБД SQL Server синтаксис "внутренних соединений" поддерживается в операторах SQL, а в СУБД Oracle не поддерживается. Но обе СУБД соответствуют стандарту SQL92. Вы можете выполнять внутренние и внешние соединения в СУБД Oracle, но по-другому, чем это делается в СУБД SQL Server. Практический результат: СУБД не так далеко "ушли" он начального уровня стандарта SQL92, поэтому если вы используете средства промежуточного или более высокого уровней, вы рискуете потерей возможности простого переноса вашего приложения в среду других СУБД.
Не бойтесь использовать специфические функциональные возможности, реализованные производителем СУБД, – в конце концов, вы платили за них большие деньги. Каждая СУБД имеет свой собственный "набор хитрых приемов", и вы всегда в любой СУБД сможете найти способ выполнения операции. Используйте все лучшее в вашей текущей СУБД, а при переходе в другую СУБД перепишите подобные компоненты. Для выделения таких изменений используйте хорошие методы программирования. Такие же методы применяются разработчиками переносимых приложений ОС. Цель: использовать все доступные средства, но обеспечить возможность изменения реализации в зависимости от конкретной ситуации.
Конкретный пример. Общая функция во многих приложениях СУБД – генерация уникального ключа для каждой строки. Когда вы вставляете строку, СУБД должна для вас автоматически сгенерировать ключ. В СУБД Oracle для этого реализован объект базы данных SEQUENCE (последовательность). В СУБД Informix – тип данных SERIAL (порядковый). В СУБД Sybase и SQL Server – тип данных IDENTITY (идентичность). В каждой СУБД – свой метод генерации ключей. Эти методы отличаются как способами их использования, так и возможными результатами. Таким образом, для хорошо осведомленного разработчика существует два пути, по которым он может следовать:
разработка способа генерации уникальных ключей, полностью независимого от конкретных СУБД;
приспосабливание к различным реализациям и использование различных методов генерации ключей в каждой СУБД.
Теоретически достоинство первого подхода заключается в том, что вы сможете переносить свое приложение из среды одной СУБД в среду другой без каких-либо изменений. Этот подход называется "теоретическим", так как "контраргументы" такой реализации настолько велики, что такое решение становится совершенно неосуществимым. Если вы собираетесь разработать процесс, полностью независимый от конкретных СУБД, вы должны создать таблицу типа:
create table id_table ( id_name varchar(30), id_value number );
insert into id_table values ( ‘MY_KEY’, 0 );
Затем для получения нового значения ключа вы должны будете выполнить:
update id_table set id_value = id_value + 1 where id_name = ‘MY_KEY’;
select id_value from id_table where id_name = ‘MY_KEY’;
Выглядит достаточно просто, но в результате такой реализации пользователи смогут выполнять транзакции только по очереди. Для увеличения значения счетчика нам нужно обновить данную строку, а это приведет к сериализации этой операции в нашей программе. В лучшем случае только один пользователь в данный момент времени сможет сгенерировать новое значение этого ключа. Проблема заключается в том, что наша транзакция может быть намного более продолжительной, чем это представлено выше. Операторы UPDATE и SELECT в нашем примере – только два оператора из множества других операторов, которые потенциально могут выполняться в нашей транзакции после генерации нового значения ключа. Такая сериализация будет существенно ограничивать масштабирование. Представьте себе использование этого метода в веб - сайтах, обрабатывающих заказы, для генерации номера каждого заказа.
Корректный подход к решению этой проблемы заключается в использовании лучших методов в каждой СУБД. В СУБД Oracle это выглядит так (предположим, необходимо генерировать значения первичного ключа таблицы T):
create table t ( pk number primary key, ... );
create sequence t_seq;
create trigger t_trigger before insert on t for each row
begin
select t_seq.nextval into :new.pk from dual;
end;
Здесь каждой вставляемой строке автоматически (и незаметно для пользователей) назначается уникальный ключ. Аналогичные результаты могут быть получены и в других СУБД с помощью средств, реализованных в них, – синтаксис операторов создания таблиц будет другим, но конечные результаты будут такими же. Мы стремимся использовать средства каждой СУБД для генерации неблокируемого уникального ключа в условиях интенсивного конкурентного доступа, и здесь мы фактически не изменяем приложение – в данном случае вся логика реализована операторами DDL.
Другой пример "безопасного программирования", учитывающий требования мобильности программного обеспечения, – реализация многоуровневого доступа к базе данных, когда это требуется (если вы понимаете, что в каждой СУБД функциональные средства реализованы по-разному). Рассмотрим программирование с использованием интерфейса JDBC (Java DataBase Connectivity – средство организации доступа Java-приложений к базам данных). Если вы используете обычные операторы SQL: SELECT, INSERT, UPDATE и DELETE), вероятно, вам не нужны уровни абстракции. Вы можете вставить операторы SQL непосредственно в приложение, если синтаксис используемых операторов поддерживается каждой СУБД, в которой вы собираетесь развернуть ваше приложение. Другой подход, обеспечивающий повышение, как уровня мобильности приложений, так и производительности, – использование хранимых процедур, возвращающих результирующие множества (resultsets). Вы обнаружите, что в каждой СУБД хранимые процедуры могут возвращать результирующие множества, но способы реализации этого различны. Реальный исходный код, который вы должны написать, будет разным в различных СУБД.
Итак, у вас есть два варианта: либо использовать хранимые процедуры, возвращающие результирующие множества, либо разрабатывать разный код для различных СУБД. Я предпочитаю следовать принципу "разный код для различных производителей". Кажется, что такой подход приводит к увеличению времени реализации приложения в разных СУБД. Однако реально вы обнаружите, что при этом подходе проще разрабатывать приложения для разных СУБД. Вместо поиска безупречных операторов SQL, которые работают во всех СУБД (возможно, в одних лучше, чем в других), вы будете использовать операторы SQL, которые лучше всего работают в данной СУБД. Вы можете делать это за пределами самого приложения, тем самым повышая гибкость настройки приложения. Вы можете исправлять медленно работающие запросы в самой СУБД, без модификации приложения. Кроме того, вы можете воспользоваться всеми преимуществами использования расширений языка SQL, сделанных данным производителем. Например, в СУБД Oracle поддерживаются иерархические запросы (с помощью предложения CONNECT BY). Эта уникальная возможность имеет большое значение при реализации рекурсивных запросов. В СУБД Oracle вы можете свободно пользоваться этим расширением языка SQL, поскольку оно реализовано "за пределами" приложений (скрыто в СУБД). В других СУБД для получения такого же результата вам, возможно, придется использовать временные таблицы и хранимые процедуры. Вы платили за такие возможности, так что можете пользоваться ими.
Аналогичные методы используют разработчики программного обеспечения для различных платформ. Корпорация Oracle, например, использует такие методы в своих разработках СУБД. Большой объем кода (небольшой процент кода всей СУБД), называемого OSD-кодом (Operating System Dependent – зависимый от операционной системы), специально разрабатывается для каждой платформы. Этот уровень абстракции позволяет использовать в СУБД Oracle многие собственные функциональные возможности конкретных ОС, обеспечивающие производительность и интеграцию. Тот факт, что СУБД Oracle может работать в ОС Windows как многопотоковое приложение, а в ОС UNIX как мультипроцессное приложение, подтверждает это. Механизмы взаимодействия процессов выносятся на такой уровень абстракции, который может быть переработан с учетом особенностей конкретной ОС, обеспечивая возможность подготовки существенно различающихся реализаций. Эти реализации выполняются как приложения, разработанные непосредственно и специально для данной платформы.
В дополнение к синтаксическим различиям в операторах SQL, различиям в реализациях и различиям в производительности выполнения одних и тех же запросов в разных СУБД, кратко рассмотренных выше, существуют проблемы конкурентного доступа, уровней изоляции транзакций, согласованности запросов и т.д. Более подробно эти вопросы мы рассмотрим в главе 3, "Блокирование и конкурентность", и в главе 4, "Транзакции". Стандарт SQL92 пытается дать непосредственные определения того, как должны работать транзакции, как должны быть реализованы уровни изоляции, но, в конечном счете, вы получите различные результаты в разных СУБД. Все это обуславливается реализацией. Для переноса приложения в другие СУБД требуются большие усилия, даже если вы на 100 процентов соблюдаете стандарт.