Страницы журнала транзакций
В отличие от версии 6.5 в новой версии под журнал транзакций отводится всегда отдельный файл. В предыдущей версии журнал транзакций являлся системной таблицей и хранился в системном сегменте LOG. Несмотря на настоятельные рекомендации располагать журнал транзакций и файлы базы данных на разных физических устройствах, СУБД автоматически не контролировала этот факт. В новой версии журнал транзакций всегда хранится в отдельном файле.
195
Рис. 9.18. Пример хранения текстовых данных на одной странице
196
191 :: 192 :: 193 :: 194 :: 195 :: 196 :: Содержание
Стратегия разрешения коллизий с областью переполнения
Первая стратегия условно может быть названа стратегией с областью переполнения. При выборе этой стратегии область хранения разбивается на 2 части:
основную область;
область переполнения.
Для каждой новой записи вычисляется значение хэш - функции, которое определяет адрес ее расположения, и запись заносится в основную область в соответствии с полученным значением хэш-функции.
167
Если вновь заносимая запись имеет значение функции хэширования такое же, которое использовала другая запись, уже имеющаяся в БД, то новая запись заносится в область переполнения на первое свободное место, а в записи-синониме, которая находится в основной области, делается ссылка на адрес вновь размещенной записи в области переполнения. Если же уже существует ссылка в записи-синониме, которая расположена в основной области, то тогда новая запись получает дополнительную информацию в виде ссылки и уже в таком виде заносится в область переполнения.
При этом цепочка синонимов не разрывается, но мы не просматриваем ее до конца, чтобы расположить новую запись в конце цепочки синонимов, а располагаем всегда новую запись на второе место в цепочке синонимов, что существенно сокращает время размещения новой записи. При таком алгоритме время размещения любой новой записи составляет не более двух обращений к диску, с учетом того, что номер первой свободной записи в области переполнения хранится в виде системной переменной.
Рассмотрим теперь механизмы поиска произвольной записи и удаления записи для этой стратегии хэширования.
При поиске записи также сначала вычисляется значение ее хэш - функции и считывается первая запись в цепочке синонимов, которая расположена в основной области. Если искомая запись не соответствует первой в цепочке синонимов, то далее поиск происходит перемещением по цепочке синонимов, пока не будет обнаружена требуемая запись. Скорость поиска зависит от длины цепочки синонимов, поэтому качество хэш - функции определяется максимальной длиной цепочки синонимов. Хорошим результатом может считаться наличие не более 10 синонимов в цепочке.
При удалении произвольной записи сначала определяется ее место расположения. Если удаляемой является первая запись в цепочке синонимов, то после удаления на ее место в основной области заносится вторая (следующая) запись в цепочке синонимов, при этом все указатели (ссылки на синонимы) сохраняются.
Если же удаляемая запись находится в середине цепочки синонимов, то необходимо провести корректировку указателей: в записи, предшествующей удаляемой, в цепочке ставится указатель из удаляемой записи. Если это последняя запись в цепочке, то все равно механизм изменения указателей такой же, то есть в предшествующую запись заносится признак отсутствия следующей записи в цепочке, который ранее хранился в последней записи.
168
167 :: 168 :: Содержание
Строки данных
Строки данных претерпели существенное изменение. Отметим наиболее важные моменты.
194
Номера строки больше нет - строка идентифицируется номером слота, который ее определяет, либо значением кластерного ключа.
В версии 6.5 поля, допускающие NULL, хранятся точно так же, как поля переменной длины. В версии 7.0 поля фиксированной длины всегда занимают свою полную длину, значение NULL задается специальным флагом. Это облегчает замену неопределенного значения на некоторое конкретное без перемещения строк на странице.
Фиксированные поля вместе с описателями хранятся до полей переменной длины, так же как и в 6.5.
В каждой строке хранится общая длина строки и текущие длины полей переменной длины. Отсутствуют таблицы смещений и подстройки смещений. Данные считываются последовательно с начального адреса.
Максимальное количество полей в строке 1024, в версии 6.5 только 256.
5 MS SQL Server логическая
В версии 6.0 и 6. 5 MS SQL Server логическая структура хранения рассматривается в следующей иерархии [1]. Файлы операционной системы представляются как устройства для хранения БД (Device), устройства нумеруются. Сервер может управлять 256 устройствами. Главное устройство называется MASTER: на нем хранятся системные базы данных: Master, Model, Pubs, TempDb.
Устройство Master имеет номер 0 - ноль.
Каждое устройство разбивается не более чем на 16 777 216 виртуальных страниц по 2 Кбайта (Virtual page), максимальный размер устройства 32 Гбайт.
Первые 4 страницы устройства Master заняты под блок конфигурации (Configuration block) - там хранятся все параметры конфигурации сервера. На устройствах размещаются конкретные базы. На каждом устройстве может быть размещено несколько баз, но и одна база может быть размещена на нескольких устройствах.
Каждая страница БД имеет свой уникальный номер.
Физически используются 3 единицы хранения данных:
страница;
блок (extent) - 16Кб из 8 следующих друг за другом страниц;
единица размещения (Allocation Unit) - 512 Кб из 32 последовательных блоков (256 страниц).
При создании новой базы данных пространство для нее отводится единицами размещения. Минимальный объем базы данных для данной версии сервера равен 1 Мбайт, то есть составляет 2 единицы размещения.
Страницы бывают пяти типов:
страницы размещения (Allocation page);
страницы данных (Data page);
индексные страницы (Index page);
текстовые страницы (Text/image page);
статистические страницы (Distribution page).
Любая страница имеет заголовок, занимающий 32 байта. Заголовок содержит номер страницы, номера предыдущей и следующей страниц, идентификатор объекта - владельца страницы и сведения о свободном пространстве на странице. Как видно из заголовка, страницы связаны в двунаправленный список.
Первая страница каждой единицы размещения является страницей размещения. Таким образом, все страницы, кратные 256, начиная с 0 являются страницами размещения. Они хранят информацию, необходимую для управления размещением страниц внутри единицы размещения.
Страница размещения содержит 32 16 - байтовых структуры, по одной на каждый блок. Каждая структура содержит следующую информацию:
идентификатор объекта - владельца блока;
188
номер следующего блока в цепи;
номер предыдущего блока в цепи;
битовую карту распределения блока (Allocation bitmap);
битовую карту перераспределения блока (Deallocation bitmap);
идентификатор индекса (если таковой есть), размещенного на блоке;
статус.
Битовая карта распределения блока хранится в единственном байте, каждый бит которого соответствует одной странице блока. Если бит равен 1, то страница в данный момент содержит данные, если 0 - то страница свободна.
Карта перераспределения применяется для отслеживания страниц, которые освобождаются в течение транзакций. Реально страница помечается как пустая только после успешной фиксации (завершения) транзакции. Это делается, чтобы другие транзакции не обращались к странице до подтверждения того факта, что она освобождена.
Все страницы в блоке могут использоваться только одной таблицей или ее индексом. Это означает, что таблица может занимать минимально 1 блок - 16 Кбайт, даже если она содержит всего несколько строк.
Страницы данных используются для хранения собственно данных. Структурно страницу данных можно подразделить на три зоны: заголовок, строки данных и таблицу смещения (см. рис. 9.14).
Рис. 9.14. Структура страницы данных для MS SQL Server 6.5
Строка данных должна полностью умещаться на странице, поэтому существуют ограничения на длину строки. Размер страницы 2048 байт, 32 байта занимает заголовок. Кроме того, в таблице смещения отводится по 2 байта на каждую строку на странице.
Страницы данных, относящиеся к одной таблице, объединяются в двунаправленный список и организуют цепочки.
Данные хранятся на страницах в виде строк (кортежей). Каждая строка данных кроме собственно данных хранит дополнительную форматирующую информацию. Длина строки зависит от определения полей таблицы и конкретных данных в ней. Независимо от объявления, каждая строка имеет номер и поле с количеством полей переменной длины (к ним относятся также поля, допускающие
189
неопределенные значения NULL). Оба эти поля имеют размер по одному байту, следовательно, количество строк на странице не превышает 256, а на количество полей также существует внешнее ограничение 250 полей в одной таблице. Структура строки таблицы приведена на рис. 9.15.
Рис. 9.15. Структура строки данных для MS SQL Server 6.5
Вторая часть - это необязательная область, она существует только тогда, когда имеются в записи поля переменной длины.
Таблица смещений (Column offset table) состоит из:
таблицы подстройки смещений (Offset table adjust bytes) - по 1 дополнительному байту на каждое поле, смещение которого превышает 256 плюс 1 байт;
указателя на местоположение таблицы смещений;
указателя на местоположение полей переменной длины (1 байт на каждое поле).
Указатели занимают два последних байта в каждой структуре и поэтому они доступны для анализа.
Структура SQL
В отличие от реляционной алгебры, где были представлены только операции запросов к БД, SQL является полным языком, в нем присутствуют не только операции запросов, но и операторы, соответствующие DDL - Data Definition Language - языку описания данных. Кроме того, язык содержит операторы, предназначенные для управления (администрирования ) БД.
SQL содержит разделы, представленные в таблице 5.1:
Таблица 5.1. Операторы определения данных DDL
Оператор | Смысл | Действие |
CREATE TABLE | Создать таблицу | Создает новую таблицу в БД |
DROP TABLE | Удалить таблицу | Удаляет таблицу из БД |
ALTER TABLE | Изменить таблицу | Изменяет структуру существующей таблицы или ограничения целостности, задаваемые для данной таблицы |
CREATE VIEW | Создать представление | Создаст виртуальную таблицу, соответствующую некоторому SQL - запросу |
ALTER VIEW | Изменить представление | Изменяет ранее созданное представление |
DROP VIEW | Удалить представление | Удаляет ранее созданное представление |
CREATE INDEX | Создать индекс | Создает индекс для некоторой таблицы для обеспечения быстрого доступа по атрибутам, входящим в индекс |
DROP INDEX | Удалить индекс | Удаляет ранее созданный индекс |
68
Таблица 5.2. Операторы манипулирования данными Data Manipulation Language (DMP)
Оператор | Смысл | Действие |
DELETE | Удалить строки | Удаляет одну или несколько строк, соответствующих условиям фильтрации, из базовой таблицы. Применение оператора согласуется с принципами поддержки целостности, поэтому этот оператор не всегда может быть выполнен корректно, даже если синтаксически он записан правильно |
INSERT | Вставить строку | Вставляет одну строку в базовую таблицу. Допустимы модификации оператора, при которых сразу несколько строк могут быть перенесены из одной таблицы или запроса в базовую таблицу |
UPDATE | Обновить строку | Обновляет значения одного или нескольких столбцов в одной или нескольких строках, соответствующих условиям фильтрации |
Таблица 5.3. Язык запросов Data Query Language (DQL)
Оператор | Смысл | Действие |
SELECT | Выбрать строки | Оператор, заменяющий все операторы реляционной алгебры и позволяющий сформировать результирующее отношение, соответствующее запросу |
Оператор | Смысл | Действие |
COMMIT | Завершить транзакцию | Завершить комплексную взаимосвязанную обработку информации, объединенную в транзакцию |
ROLLBACK | Откатить транзакцию | Отменить изменения, проведенные в ходе выполнения транзакции |
SAVEPOINT | Сохранить промежуточную точку выполнения транзакции | Сохранить промежуточное состояние БД, пометить его для того, чтобы можно было в дальнейшем к нему вернуться |
Оператор | Смысл | Действие |
ALTER DATABASE | Изменить БД | Изменить набор основных объектов в базе данных, ограничений, касающихся всей базы данных |
ALTER DBAREA | Изменить область хранения БД | Изменить ранее созданную область хранения |
Таблица 5.5 (продолжение)
Оператор | Смысл | Действие |
ALTER PASSWORD | Изменить пароль | Изменить пароль для всей базы данных |
CREATE DATABASE | Создать БД | Создать новую базу данных, определив основные параметры для нее |
CREATE DBAREA | Создать область хранения | Создать новую область хранения и сделать ее доступной для размещения данных |
DROP DATABASE | Удалить БД | Удалить существующую базу данных (только в том случае, когда вы имеете право выполнить это действие) |
DROP DBAREA | Удалить область хранения БД | Удалить существующую область хранения (если в ней на настоящий момент не располагаются активные данные) |
GRANT | Предоставить права | Предоставить права доступа на ряд действий над некоторым объектом БД |
REVOKE | Лишить прав | Лишить прав доступа к некоторому объекту или некоторым действиям над объектом |
Оператор | Смысл | Действие |
DECLARE | Определяет курсор для запроса | Задает некоторое имя и определяет связанный с ним запрос к БД, который соответствует виртуальному набору данных |
OPEN | Открыть курсор | Формирует виртуальный набор данных, соответствующий описанию указанного курсора и текущему состоянию БД |
FETCH | Считать строку из множества строк, определенных курсором | Считывает очередную строку, заданную параметром команды из виртуального набора данных, соответствующего открытому курсору |
CLOSE | Закрыть курсор | Прекращает доступ к виртуальному набору данных, соответствующему указанному курсору |
PREPARE | Подготовить оператор SQL к динамическому выполнению | Сгенерировать план выполнения запроса, соответствующего заданному оператору SQL |
Оператор | Смысл | Действие |
EXECUTE | Выполнить оператор SQL, ранее подготовленный к динамическому выполнению | Выполняет ранее подготовленный план запроса |
В новой версии сервера баз
В новой версии сервера баз данных фирма Microsoft реализовала абсолютно новый механизм хранения.
SQL Server 7.0 организует следующую иерархию хранения:
191
База данных - некоторый объем физического пространства, на котором размещаются данные, принадлежащие одной логической базе данных.
Файл. Каждая база данных содержит не менее двух файлов. Один из них отводится под журнал транзакций. И в отличие от версии 6.5 в новой версии журнал транзакций не может располагаться в одном файле с данными. И еще одно принципиальное отличие - в новой версии каждый файл может принадлежать только одной базе данных, у нас не может быть разделяемых файлов.
Страница. Файлы делятся на страницы размером по 8 Кбайт каждая. Логический номер страницы складывается из внутреннего номера базы данных, номера файла и номера страницы в файле. В рамках БД файлы нумеруются, начиная с 1, и так же нумеруются страницы в рамках файла.
Блоки (экстенты, extents). Пространство под объекты отводится блоками по 8 следующих друг за другом страниц. Блок является основной единицей отведения пространства. Поэтому при создании БД можно указывать размер файла с точностью до 64 Кбайт. Для суперкомпьютеров заложена возможность увеличения размера блоков до 128 страниц.
В отличие от версии 6.5 объекты БД не обязательно занимают целый блок. На начальном этапе заполнения объект может занимать внутри блока несколько страниц. Поэтому существуют два типа блоков:
Однородные (Uniform). Все страницы однородного блока принадлежат одному объекту БД.
Смешанные (Mixed). Разные страницы в блоке принадлежат разным объектам.
Когда объект создается, то обычно его первые страницы отводятся в смешанном блоке, по мере роста объекта он уже размещается в однородных блоках.
В SQL 7.0 существуют уже 7 типов страниц:
страница данных (Data page);
индексные страницы (Index page);
страницы журнала транзакций (Log page);
текстовые страницы (Text/image page);
карты распределения блоков (Global allocation map page);
карты свободного пространства (Page free space page);
индексные карты размещения (Index allocation map page).
Все страницы имеют заголовок размером 96 байтов. В заголовке хранится общая информация, используемая ядром СУБД для работы со страницами. На странице в отличие от блока хранится однородная информация. Поэтому среди параметров страницы задаются:
номер страницы в формате ;
идентификатор объекта, которому принадлежит страница;
номер индекса, которому принадлежит страница;
уровень внутри индексного дерева, которому принадлежит страница;
192
количество отведенных строк на странице, количество заполненных слотов;
общий объем свободного пространства на странице;
указатель на расположение свободного пространства после последней строки на странице;
минимальная длина строки на странице;
объем зарезервированного пространства.
После заголовка следует информация о статусе страницы в картах распределения блоков и карте свободного пространства.
Новыми в архитектуре дисковой памяти являются страницы размещения. В этих страницах хранятся сведения о размещении данных. SQL Server 7.0 использует три типа страниц размещения: карты распределения блоков, карты свободного пространства, индексные карты размещения. SQL Server 7.0 хранит информацию размещения на разных уровнях: на уровне блоков, на уровне страниц, на уровне объектов. Такой разносторонний мониторинг помогает СУБД оптимизировать работу в соответствии с требованиями конкретного запроса.
Свойства транзакций. Способы завершения транзакций
Существуют различные модели транзакций, которые могут быть классифицированы на основании различных свойств, включающих структуру транзакции, параллельность внутри транзакции, продолжительность и т. д.
В настоящий момент выделяют следующие типы транзакций: плоские или классические транзакции, цепочечные транзакции и вложенные транзакции.
Плоские, или традиционные, транзакции, характеризуются четырьмя классическими свойствами: атомарности, согласованности, изолированности, долговечности (прочности) - ACID (Atomicity, Consistency, Isolation, Durability). Иногда традиционные транзакции называют ACID-транзакциями. Упомянутые выше свойства означают следующее:
Свойство атомарности (Atomicity) выражается в том, что транзакция должна быть выполнена в целом или не выполнена вовсе.
Свойство согласованности (Consistency) гарантирует, что по мере выполнения транзакций данные переходят из одного согласованного состояния в другое -транзакция не разрушает взаимной согласованности данных.
Свойство изолированности (Isolation) означает, что конкурирующие за доступ к базе данных транзакции физически обрабатываются последовательно, изолированно друг от друга, но для пользователей это выглядит так, как будто они выполняются параллельно.
Свойство долговечности (Durability) трактуется следующим образом: если транзакция завершена успешно, то те изменения в данных, которые были ею произведены, не могут быть потеряны ни при каких обстоятельствах (даже в случае последующих ошибок).
Возможны два варианта завершения транзакции. Если все операторы выполнены успешно и в процессе выполнения транзакции не произошло никаких сбоев программного или аппаратного обеспечения, транзакция фиксируется.
Фиксация транзакции - это действие, обеспечивающее запись на диск изменений в базе данных, которые были сделаны в процессе выполнения транзакции.
217
До тех пор пока транзакция не зафиксирована, допустимо аннулирование этих изменений, восстановление базы данных в то состояние, в котором она была на момент начала транзакции.
Фиксация транзакции означает, что все результаты выполнения транзакции становятся постоянными. Они станут видимыми другим транзакциям только после того, как текущая транзакция будет зафиксирована. До этого момента все данные, затрагиваемые транзакцией, будут "видны" пользователю в состоянии на начало текущей транзакции.
Если в процессе выполнения транзакции случилось нечто такое, что делает невозможным ее нормальное завершение, база данных должна быть возвращена в исходное состояние. Откат транзакции - это действие, обеспечивающее аннулирование всех изменений данных, которые были сделаны операторами SQL в теле текущей незавершенной транзакции.
Каждый оператор в транзакции выполняет свою часть работы, но для успешного завершения всей работы в целом требуется безусловное завершение всех их операторов. Группирование операторов в транзакции сообщает СУБД, что вся эта группа должна быть выполнена как единое целое, причем такое выполнение должно поддерживаться автоматически.
В стандарте ANSI/ISO SQL определены модель транзакций и функции операторов COMMIT и ROLLBACK. Стандарт определяет, что транзакция начинается с первого SQL-оператора, инициируемого пользователем или содержащегося в программе, изменяющего текущее состояние базы данных. Все последующие SQL-операторы составляют тело транзакции. Транзакция завершается одним из четырех возможных путей (рис. 11.1):
оператор COMMIT означает успешное завершение транзакции; его использование делает постоянными изменения, внесенные в базу данных в рамках текущей транзакции;
оператор ROLLBACK прерывает транзакцию, отменяя изменения, сделанные в базе данных в рамках этой транзакции; новая транзакция начинается непосредственно после использования ROLLBACK;
успешное завершение программы, в которой была инициирована текущая транзакция, означает успешное завершение транзакции (как будто был использован оператор COMMIT);
ошибочное завершение программы прерывает транзакцию (как будто был использован оператор ROLLBACK).
В этой модели каждый оператор, который изменяет состояние БД, рассматривается как транзакция, поэтому при успешном завершении этого оператора БД переходит в новое устойчивое состояние.
В первых версиях коммерческих СУБД была реализована модель транзакций ANSI/ISO. В дальнейшем в СУБД SYBASE была реализована расширенная модель транзакций, которая включает еще ряд дополнительных операций. В модели SYBASE используются следующие четыре оператора:
Оператор BEGIN TRANSACTION сообщает о начале транзакции. В отличие от модели в стандарте ANSI/ISO, где начало транзакции неявно задается первым оператором модификации данных, в модели SYBASE начало транзакции задается явно с помощью оператора начала транзакции.
218
Оператор COMMIT TRANSACTION сообщает об успешном завершении транзакции. Он эквивалентен оператору COMMIT в модели стандарта ANSI/ISO. Этот оператор, как и оператор COMMIT, фиксирует все изменения, которые производились в БД в процессе выполнения транзакции.
Оператор SAVE TRANSACTION создает внутри транзакции точку сохранения, которая соответствует промежуточному состоянию БД, сохраненному на момент выполнения этого оператора. В операторе SAVE TRANSACTION может стоять имя точки сохранения. Поэтому в ходе выполнения транзакции может быть запомнено несколько точек сохранения, соответствующих нескольким промежуточным состояниям.
Оператор ROLLBACK имеет две модификации. Если этот оператор используется без дополнительного параметра, то он интерпретируется как оператор отката всей транзакции, то есть в этом случае он эквивалентен оператору отката ROLLBACK в модели ANSI/ISO. Если же оператор отката имеет параметр и записан в виде ROLLBACK В, то он интерпретируется как оператор частичного отката транзакции в точку сохранения В.
Рис. 11.1. Модель транзакций ANSI/ISO
Принципы выполнения транзакций в расширенной модели транзакций представлены на рис. 11.2. На рисунке операторы помечены номерами, чтобы нам удобнее было проследить ход выполнения транзакции во всех допустимых случаях.
219
Рис. 11.2. Примеры выполнения транзакций в расширенной модели
Транзакция начинается явным оператором начала транзакции, который имеет в нашей схеме номер 1. Далее идет оператор 2, который является оператором поиска и не меняет текущее состояние БД, а следующие за ним операторы 3 и 4 переводят базу данных уже в новое состояние. Оператор 5 сохраняет это новое промежуточное состояние БД и помечает его как промежуточное состояние в точке А. Далее следуют операторы 6 и 7, которые переводят базу данных в новое состояние. А оператор 8 сохраняет это состояние как промежуточное состояние в точке В. Оператор 9 выполняет ввод новых данных, а оператор 10 проводит некоторую проверку условия 1; если условие 1 выполнено, то выполняется
220
оператор 11, который проводит откат транзакции в промежуточное состояние В. Это означает, что последствия действий оператора 9 как бы стираются и база данных снова возвращается в промежуточное состояние В, хотя после выполнения оператора 9 она уже находилась в новом состоянии. И после отката транзакции вместо оператора 9, который выполнялся раньше из состояния В БД, выполняется оператор 13 ввода новых данных, и далее управление передается оператору 14. Оператор 14 снова проверяет условие, но уже некоторое новое условие 2; если условие выполнено, то управление передается оператору 15, который выполняет откат транзакции в промежуточное состояние А, то есть все операторы, которые изменяли БД, начиная с 6 и заканчивая 13, считаются невыполненными, то есть результаты их выполнения исчезли и мы снова находимся в состоянии А, как после выполнения оператора 4. Далее управление передается оператору 17, который обновляет содержимое БД, после этого управление передается оператору 18, который связан с проверкой условия 3. Проверка заканчивается либо передачей управления оператору 20, который фиксирует транзакцию, и БД переходит в новое устойчивое состояние, и изменить его в рамках текущей транзакции невозможно. Либо, если управление передано оператору 19, то транзакция откатывается к началу и БД возвращается в свое начальное состояние, а все промежуточные состояния здесь уже проверены, и выполнить операцию отката в эти промежуточные состояния после выполнения оператора 19 невозможно.
Конечно, расширенная модель транзакции, предложенная фирмой SYBASE, поддерживает гораздо более гибкий механизм выполнения транзакций. Точки сохранения позволяют устанавливать маркеры внутри транзакции таким образом, чтобы имелась возможность отмены только части работы, проделанной в транзакции. Целесообразно использовать точки сохранения в длинных и сложных транзакциях, чтобы обеспечить возможность отмены изменения для определенных операторов. Однако это обусловливает дополнительные затраты ресурсов системы - оператор выполняет работу, а изменения затем отменяются; обычно усовершенствования в логике обработки могут оказаться более оптимальным решением.
Таблица смещения строк
Местоположение строки на странице определяется таблицей смещения строк (Row offset table). Таблица располагается в самом конце страницы и забирает дополнительно по 2 байта на каждую строку данных (см. рис. 9.16). Чтобы найти строку с заданным номером, SQL Server считывает из соответствующей ячейки смещение, которое и является адресом требуемой строки. Ячейка таблицы однозначно связана с определенным номером строки.
Удаленные строки имеют нулевое смещение. Поэтому из примера на рис. 9.16 видно, что строки 1 и 4 удалены.
У этой модели есть недостаток. После удаления строки в таблице смещения все равно остается ссылка на нее, которая занимает 1 байт. Однако при добавлении новой строки SQL Server проверяет таблицу смещений и ищет нулевое смещение, и новой строке присваивается номер удаленной, а в соответствующую ячейку таблицы смещений заносится адрес новой строки.
В SQL Server 6.5 используется понятие кластерного индекса. В таблице, для которой создается кластерный индекс, данные хранятся строго упорядочение по
190
полю, для которого создан этот кластерный индекс. Это поле (или набор полей) является первичным ключом таблицы или обладает свойством уникальности. При заполнении таблиц с кластерным индексом вводится параметр, соответствующий проценту заполнения страницы (fill-factor). Если страница заполнена, то данные заносятся на последнюю страницу в цепочке страниц, занятых этой таблицей.
Рис. 9.16. Пример заполнения таблицы смещения строк
Некластерный индекс хранится отдельно от данных.
Текстовые страницы предназначены для хранения данных типа Next или Image.
На одной текстовой странице хранятся только данные одной строки основной таблицы (см. рис. 9.17). В основной таблице в соответствующем месте хранится только ссылка на соответствующую текстовую страницу. Если неструктурированные данные не умещаются на одной странице, то они образуют цепочку взаимосвязанных страниц.
Рис. 9.17. Хранение текстовых данных
191
188 :: 189 :: 190 :: 191 :: Содержание
Текстовые Страницы
В версии 7.0 изменены принципы хранения текстовых полей. Строки данных по-прежнему содержат 16 - байтные указатели на текстовые данные. Однако хранение самих текстовых данных производится иначе.
Текстовая страница теперь может содержать несколько текстовых полей. Собственно данные хранятся в виде сбалансированного дерева (В-tree). Строка данных содержит указатель на корневую структуру (Root structure) размером 84 байта.
Данные длиной менее 64 байт хранятся в корневой структуре. Для данных до 32 Кбайт корневая структура (Root structure) может адресовать 4 блока данных (это не блоки страниц) до 8 Кбайт каждый. Блоки наращиваются до 8 Кбайт (реально на одной текстовой странице может быть размещено 8080 байт). Например, если первая порция данных составляет 4 Кбайта, то отводится один блок. Если в дальнейшем данные увеличиваются до 6 Кбайт, то первый блок увеличивается до 6 Кбайт, а второй блок имеет размер всего 2 Кбайта.
Если же длина текстового поля более 32 Кбайт, то строятся промежуточные узлы.
В версии 7.0 текстовая страница может содержать данные нескольких текстовых полей (рис. 9.18).
Теоретико-множественные операции реляционной алгебры
Объединением двух отношений называется отношение, содержащее множество кортежей, принадлежащих либо первому, либо второму исходным отношениям, либо обоим отношениям одновременно.
Пусть заданы два отношения R1 = { r1 } , R2 = { r2 }, где r1 и r2 - соответственно кортежи отношений R1 и R2, то объединение
R1 ? R2 = { r | r ? R1 ? r ? R2 }.
Здесь r - кортеж нового отношения, v - операция логического сложения "ИЛИ".
Пример применения операции объединения приведен па рис. 4.1. Исходными отношениями являются отношения R1 и R2, которые содержат перечни деталей, изготавливаемых соответственно на первом и втором участках цеха. Отношение R3 содержит общий перечень деталей, изготавливаемых в цеху, то есть характеризует общую номенклатуру цеха.
|
|
51
R3 | |
Шифр детали | Название детали |
00011073 | Гайка Ml |
00011075 | Гайка М2 |
00011076 | Гайка М3 |
00011003 | Болт Ml |
00011006 | Болт М3 |
00013063 | Шайба Ml |
00013066 | Шайба М3 |
00011077 | Гайка М4 |
00011004 | Болт М2 |
Пересечением отношений называется отношение, которое содержит множество кортежей, принадлежащих одновременно и первому и второму отношениям. R1 и R2:
R3 = R1 ? R2 ={ r | r ? R1 ? r ? R2 }
здесь ? - операция логического умножения (логическое "И").
В отношении R4 содержатся перечень деталей, которые выпускаются одновременно на двух участках цеха.
R4 | |
Шифр детали | Название детали |
00011073 | Гайка Ml |
00011076 | Гайка М3 |
00011006 | Болт М3 |
Разностью отношений R1 и R2 называется отношение, содержащее множество кортежей, принадлежащих R1 и не принадлежащих R2:
R5 = R1 \ R2 = { r | r ? R1 ? r ?/ R2 }
Отношение R5 содержит перечень деталей, изготавливаемых только на участке 1, отношение R6 содержит перечень деталей, изготавливаемых только на участке 2.
R6 = R2 \ R1 = { r | r ? R2 ? r ?/ R1 }
|
|
Следует отметить, что первые две операции, объединение и пересечение, являются коммутативными операциями, то есть результат операции не зависит от порядка аргументов в операции. Операция же разности является принципиально несимметричной операцией, то есть результат операции будет различным для разного порядка аргументов, что и видно из сравнения отношений R5 и R6.
В отличие от навигационных средств манипулирования данными в теоретико - графовых моделях операции реляционной алгебры позволяют получить сразу иной качественный результат, который является семантически гораздо более ценным и понятным пользователям. Например, сравнение результатов объединения и разности номенклатуры двух участков позволит оценить специфику производства: насколько оно уникально на каждом участке, и, в зависимости от необходимости, принять соответствующее решение по изменению номенклатуры.
Для демонстрации возможностей трех первых операций реляционной алгебры рассмотрим еще один пример - уже из другой предметной области. Исходными являются три отношения R1, R2 и R3. Все они имеют эквивалентные схемы.
R1 = (ФИО, Паспорт, Школа);
R2 = (ФИО, Паспорт, Школа);
R3 = (ФИО, Паспорт, Школа).
Рассмотрим ситуацию поступления в высшие учебные заведения, которая была характерна для периода, когда были разрешены так называемые репетиционные вступительные экзамены, которые сдавались раньше основных вступительных экзаменов в вуз. Отношение R1 содержит список абитуриентов, сдававших репетиционные экзамены. Отношение R2 содержит список абитуриентов, сдававших экзамены на общих условиях. И наконец, отношение R3 содержит список абитуриентов, принятых в институт. Будем считать, что при неудачной сдаче репетиционных экзаменов абитуриент мог делать вторую попытку и сдавать экзамены в общем потоке, поэтому некоторые абитуриенты могут присутствовать как в первом, так и во втором отношении.
Ответим на следующие вопросы:
1. Список абитуриентов, которые поступали два раза и не поступили в вуз.
R = R1 ? R2 \ R3
2. Список абитуриентов, которые поступили в вуз с первого раза, то есть они сдавали экзамены только один раз и сдали их так хорошо, что сразу были зачислены в вуз.
R = (R1 \ R2 ? R3) ? (R2 \ R1 ? R3)
3. Список абитуриентов, которые поступили в вуз только со второго раза.
Прежде всего это те абитуриенты, которые присутствуют в отношениях R1 и R2, потому что они поступали два раза, и присутствуют в отношении R3, потому что они поступили.
R = R1 ? R2 ? R3
4. Список абитуриентов, которые поступали только один раз и не поступили.
Это прежде всего те абитуриенты, которые присутствуют в R1 и не присутствуют в R2, и те, кто присутствуют в R2 и не присутствуют в R1. И разумеется, никто из них не присутствует в R3.
53
R = (R1 \ R2) ? (R2 \ R1) \ R3
В отсутствие скобок порядок выполнения операций реляционной алгебры естественный, поэтому сначала будут выполнены операции в скобках, а затем будет выполнена последняя операция вычитания отношения R3.
Операции объединения, пересечения и разнести применимы только к отношениям с эквивалентными схемами.
Кроме перечисленных трех теоретико-множественных операций в рамках реляционной алгебры определена еще одна теоретико-множественная операция -расширенное декартово произведение. Эта операция не накладывает никаких дополнительных условий на схемы исходных отношений, поэтому операция расширенного декартова произведения, обозначаемая R1 ? R2, допустима для любых двух отношений. Но прежде чем определить саму операцию, введем дополнительно понятие конкатенации, или сцепления, кортежей.
Сцеплением, или конкатенацией, кортежей с = 1, с2, ..., сn> и q = 1, q2, ..., qm> называется кортеж, полученный добавлением значений второго в конец первого. Сцепление кортежей с и q обозначается как (с , q).
(с, q) = 1, с2, ... , сn, q1, q2, ..., qm>
Здесь n - число элементов в первом кортеже с, m - число элементов во втором кортеже q.
Все предыдущие операции не меняли степени или арности отношений - это следует из определения эквивалентности схем отношений. Операция декартова произведения меняет степень результирующего отношения.
Расширенным декартовым произведением отношения R1 степени n со схемой
SR1 = (А1, А2, ... , Аn)
и отношения R2 степени m со схемой
SR2 = (В1, В2, ... , Вm)
называется отношение R3 степени n+m со схемой
SR3 = (А1, А2, ... , Аn, В1, В2, ..., Вm),
содержащее кортежи, полученные сцеплением каждого кортежа r отношения R1 с каждым кортежем q отношения R2.
То есть если R1 = { r }, R2 = { q }
R1 ? R2 - {(r, q) | r ? R1 ? q ? R2}
Операцию декартова произведения с учетом возможности перестановки атрибутов в отношении можно считать симметричной. Очень часто операция расширенного декартова произведения используется для получения некоторого универсума - т. е. отношения, которое характеризует все возможные комбинации между элементами отдельных множеств. Однако самостоятельного значения результат выполнения операции обычно не имеет, он участвует в дальнейшей обработке. Например, на производстве в отношении 07 задана обязательная номенклатура деталей для всех цехов, а в отношении 08 дан перечень всех цехов.
54
|
|
|
|
|
|
Отношение R11, которое является результатом выполнения этой операции, имеет вид:
R11 = R9 \ R10
56
R11 | ||
Шифр детали | Название детали | Цех |
00011073 | Гайка Ml | Цех 2 |
00011075 | Гайка М2 | Цех 2 |
00011076 | Гайка М3 | Цех 2 |
00011004 | Болт М2 | Цех 3 |
00013062 | Шайба М2 | Цех 3 |
00011003 | Болт Ml | Цех 2 |
00011005 | Болт М5 | Цех 3 |
(R1 ? R2) \ (R1 \ R2) \ (R2 \ R1)
Однако это достаточно сложная формула, и именно поэтому все три теоретико-множественные операции вошли в базовый набор операций реляционной алгебры.
Далее мы переходим к группе операций, названных специальными операциями реляционной алгебры.
Терминология
Пользователь БД - программа или человек, обращающийся к БД на ЯМД.
Запрос - процесс обращения пользователя к БД с целью ввода, получения или изменения информации в БД.
Транзакция - последовательность операций модификации данных в БД, переводящая БД из одного непротиворечивого состояния в другое непротиворечивое состояние.
Логическая структура БД - определение БД на физически независимом уровне, ближе всего соответствует концептуальной модели БД.
Топология БД = Структура распределенной БД - схема распределения физической БД по сети.
Локальная автономность - означает, что информация локальной БД и связанные с ней определения данных принадлежат локальному владельцу и им управляются.
Удаленный запрос - запрос, который выполняется с использованием модемной связи.
Возможность реализации удаленной транзакции - обработка одной транзакции, состоящей из множества SQL-запросов на одном удаленном узле.
Поддержка распределенной транзакции - допускает обработку транзакции, состоящей из нескольких запросов SQL, которые выполняются на нескольких узлах сети (удаленных или локальных), но каждый запрос в "этом случае обрабатывается
199
только на одном узле, то есть запросы не являются распределенными. При обработке одной распределенной транзакции разные локальные запросы могут обрабатываться в разных узлах сети.
Распределенный запрос - запрос, при обработке которого используются данные из БД, расположенные в разных узлах сети.
Системы распределенной обработки данных в основном связаны с первым поколением БД, которые строились на мультипрограммных операционных системах и использовали централизованное хранение БД на устройствах внешней памяти центральной ЭВМ и терминальный многопользовательский режим доступа к ней. При этом пользовательские терминалы не имели собственных ресурсов -то есть процессоров и памяти, которые могли бы использоваться для хранения и обработки данных. Первой полностью реляционной системой, работающей в многопользовательском режиме, была СУБД SYSTEM R, разработанная фирмой IBM, именно в ней были реализованы как язык манипулирования данными SQL, так и основные принципы синхронизации, применяемые при распределенной обработке данных, которые до сих пор являются базисными практически во всех коммерческих СУБД.
Общая тенденция движения от отдельных mainframe-систем к открытым распределенным системам, объединяющим компьютеры среднего класса, получила название DownSizing. Этот процесс оказал огромное влияние на развитие архитектур СУБД и поставил перед их разработчиками ряд сложных задач. Главная проблема состояла в технологической сложности перехода от централизованного управления данными на одном компьютере и СУБД, использовавшей собственные модели, форматы представления данных и языки доступа к данным и т. д., к распределенной обработке данных в неоднородной вычислительной среде, состоящей из соединенных в глобальную сеть компьютеров различных моделей и производителей.
В то же время происходил встречный процесс - UpSizing. Бурное развитие персональных компьютеров, появление локальных сетей также оказали серьезное влияние на эволюцию СУБД. Высокие темпы роста производительности и функциональных возможностей PC привлекли внимание разработчиков профессиональных СУБД, что привело к их активному распространению на платформе настольных систем.
Сегодня возобладала тенденция создания информационных систем на такой платформе, которая точно соответствовала бы ее масштабам и задачам. Она получила название RightSizing (помещение ровно в тот размер, который необходим).
Однако и в настоящее время большие ЭВМ сохраняются и сосуществуют с современными открытыми системами. Причина этого проста - в свое время в аппаратное и программное обеспечение больших ЭВМ были вложены огромные средства: в результате многие продолжают их использовать, несмотря на морально устаревшую архитектуру. В то же время перенос данных и программ с больших ЭВМ на компьютеры нового поколения сам по себе представляет сложную техническую проблему и требует значительных затрат.
Типы данных
В языке SQL/89 поддерживаются следующие типы данных:
CHARACTER(n) или CHAR(n) - символьные строки постоянной длины в n символов. При задании данного типа под каждое значение всегда отводится п символов, и если реальное значение занимает менее, чем п символов, то СУБД автоматически дополняет недостающие символы пробелами.
NUMERIC[(n,m)] - точные числа, здесь n - общее количество цифр в числе, m - количество цифр слева от десятичной точки.
DECIMAL[(n,m)] - точные числа, здесь n - общее количество цифр в числе, m - количество цифр слева от десятичной точки.
DEC[(n,m)] - то же, что и DECIMAL[(n,m)].
INTEGER или INT - целые числа.
SMALLINT - целые числа меньшего диапазона.
Несмотря на то, что в стандарте SQL1 не определяется точно, что подразумевается под типом INT и SMALLINT (это отдано на откуп реализации), указано только соотношение между этими типами данных, в большинстве реализаций тип данных INTEGER соответствует целым числам, хранимым в четырех байтах, a SMALLINT - соответствует целым числам, хранимым в двух байтах. Выбор одного из этих типов определяется размером числа.
FLOAT[(n)] - числа большой точности, хранимые в форме с плавающей точкой. Здесь n - число байтов, резервируемое под хранение одного числа. Диапазон чисел определяется конкретной реализацией.
REAL - вещественный тип чисел, который соответствует числам с плавающей точкой, меньшей точности, чем FLOAT.
DOUBLE PRECISION специфицирует тип данных с определенной в реализации точностью большей, чем определенная в реализации точность для REAL.
В стандарте SQL92 добавлены следующие типы данных:
VARCHAR(n) - строки символов переменной длины.
NCHAR(N) - строки локализованных символов постоянной длины.
71
NCHAR VARYING(n) - строки локализованных символов переменной длины.
BIT(n) - строка битов постоянной длины.
BIT VARYING(n) - строка битов переменной длины.
DATE - календарная дата.
ТIMESTAMP(точность) - дата и время.
INTERVAL - временной интервал.
Большинство коммерческих СУБД поддерживают еще дополнительные типы данных, которые не специфицированы в стандарте.
Так, например, практически все СУБД в том или ином виде поддерживают тип данных для представления неструктурированного текста большого объема. Этот тип аналогичен типу MEMO в настольных СУБД. Называются эти типы по-разному, например в ORACLE этот тип называется LONG, в DB2 - LONG VARCHAR, в SYBASE и MS SQL Server - TEXT.
Однако следует отметить, что специфика реализации отдельных типов данных серьезным образом влияет на результаты запросов к БД. Особенно это касается реализации типов данных DATE и TIMESTAMP. Поэтому при переносе приложений будьте внимательны, на разных платформах они могут работать по-разному, и одной из причин может быть различие в интерпретации типов данных.
При выполнении сравнений в операциях фильтрации могут использоваться константы заданных типов. В стандарте определены следующие константы. Для числовых типов данных определены константы в виде последовательности цифр с необязательным заданием знака числа и десятичной точкой. То есть правильными будут константы:
213-314 | 612.716 | + 551.702 |
2.9Е-4 | -134.235Е7 | 0.54267Е18 |
'Крылов Ю.Д.' | 'Санкт-Петербург' |
"Москва" | "New York" |
Константы даты, времени и временного интервала в реляционных СУБД представляются в виде строковых констант. Форматы этих констант отличаются в различных СУБД. Кроме того, формат представления даты различен в разных странах. В большинстве СУБД реализованы способы настройки форматов
72
представления дат или специальные функции преобразования форматов дат, как сделано, например, в СУБД ORACLE. Приведем примеры констант в MS SQL Server:
March 15. 1999 Маг 15 1999 3/15/19993-15-99 1999 MAR 15
В СУБД ORACLE та же константа запишется как
15-MAR-99
Кроме пользовательских констант в СУБД могут существовать и специальные системные константы. Стандарт SQL1 определяет только одну системную константу USER, которая соответствует имени пользователя, под которым вы подключились к БД.
В операторах SQL могут использоваться выражения, которые строятся по стандартным правилам применения знаков арифметических операций сложения (+), вычитания (-), умножения (*) и деления (/). Однако в ряде СУБД операция деления (/) интерпретируется как деление нацело, поэтому при построении сложных выражений вы можете получить результат, не соответствующий традиционной интерпретации выражения. В стандарт SQL2 включена возможность выполнения операций сложения и вычитания над датами. В большинстве СУБД также определена операция конкатенации над строковыми данными, обозначается она, к сожалению, по-разному. Так, например, для DB2 операция конкатенации обозначается двойной вертикальной чертой, в MS SQL Server - знаком сложения (+), поэтому два выражения, созданные в разных СУБД, эквивалентны:
?Mr./Mrs. ? | | NAME | | ? ? LAST_NAME
?Mr./Mrs. ? + NAME + ? ? LAST_NAME
В стандарте SQL1 не были определены встроенные функции, однако в большинстве коммерческих СУБД такие функции были реализованы, и в стандарт SQL2 уже введен ряд стандартных встроенных функций:
BIT_LENGTH(строка) - количество битов в строке;
САSТ(значение AS тип данных) - значение, преобразованное в заданный тип данных;
CHAR_LENGTH(строка) - длина строки символов;
CONVERT(строка USING функция) - строка, преобразованная в соответствии с указанной функцией;
CURRENT_DATE - текущая дата;
CURRENT_TIME(точность) - текущее время с указанной точностью;
CURRENT_TIMESTAMP(точность) - текущие дата и время с указанной точностью;
LOWER(строка) - строка, преобразованная к верхнему регистру;
OCTED_LENGTH(строка) - число байтов в строке символов;
POSITION( первая строка IN вторая строка) - позиция, с которой начинается вхождение первой строки во вторую;
73
SUBSTRING(строка FROM n FOR длина) - часть строки, начинающаяся с n - го символа и имеющая указанную длину;
ТRАNSLATE(строка USING функция) - строка, преобразованная с использованием указанной функции;
TRIM(BOTH символ FROM строка) - строка, у которой удалены все первые и последние символы;
TRIM(LEADING символ FROM строка ) - строка, в которой удалены все первые указанные символы;
TRIM(TRAILING символ FROM строка) - строка, в которой удалены последние указанные символы;
UPPER(строка) - строка, преобразованная к верхнему регистру.
Типы параллелизма
Рассматривают несколько путей распараллеливания запросов.
Горизонтальный параллелизм. Этот параллелизм возникает тогда, когда хранимая в БД информация распределяется по нескольким физическим устройствам хранения - нескольким дискам. При этом информация из одного отношения разбивается на части по горизонтали (см. рис. 10.13). Этот вид параллелизма иногда называют распараллеливанием или сегментацией данных. И параллельность здесь достигается путем выполнения одинаковых операций, например фильтрации, над разными физическими хранимыми данными. Эти операции могут выполняться параллельно разными процессами, они независимы. Результат выполнения целого запроса складывается из результатов выполнения отдельных операций.
Время выполнения такого запроса при соответствующем сегментировании данных существенно меньше, чем время выполнения этого же запроса традиционными способами одним процессом.
Вертикальный параллелизм. Этот параллелизм достигается конвейерным выполнением операций, составляющих запрос пользователя. Этот подход требует серьезного усложнения в модели выполнения реляционных операций ядром СУБД. Он предполагает, что ядро СУБД может произвести декомпозицию запроса, базируясь на его функциональных компонентах, и при этом ряд подзапросов может выполняться параллельно, с минимальной связью между отдельными шагами выполнения запроса.
Действительно, если мы рассмотрим, например, последовательность операций реляционной алгебры:
R5 = R1 [ А.С]
R6 = R2 [A.B.D]
R7 = R5[A > 128]
R8 = R5[A]R6.
то операции первую и третью можно объединить и выполнить параллельно с операцией два, а затем выполнить над результатами последнюю четвертую операцию.
Общее время выполнения подобного запроса, конечно, будет существенно меньше, чем при традиционном способе выполнения последовательности из четырех операций (см. рис. 10.13).
И третий вид параллелизма является гибридом двух ранее рассмотренных (см. рис. 10.14).
Наиболее активно применяются все виды параллелизма в OLAP-приложениях, где эти методы позволяют существенно сократить время выполнения сложных запросов над очень большими объемами данных.
214
Рис. 10.13. Выполнение запроса при вертикальном параллелизме
Рис. 10.14. Выполнение запроса при гибридном параллелизме
215
214 :: 215 :: Содержание
Триггеры
Фактически триггер - это специальный вид хранимой процедуры, которую SQL Server вызывает при выполнении операций модификации соответствующих таблиц. Триггер автоматически активизируется при выполнении операции, с которой он связан. Триггеры связываются с одной или несколькими операциями модификации над одной таблицей.
В разных коммерческих СУБД рассматриваются разные триггеры. Так, в MS SQL Server триггеры определены только как постфильтры, то есть такие триггеры, которые выполняются после свершения события.
В СУБД Oracle определены два типа триггеров: триггеры, которые могут быть запущены перед реализацией операции модификации, они называются BEFORE-триггерами, и триггеры, которые активизируются после выполнения соответствующей модификации, аналогично триггерам MS SQL Server, - они называются AFTER - триггерами.
Триггеры могут быть эффективно использованы для поддержки семантической целостности БД, однако приоритет их ниже, чем приоритет правил-ограничений (constraints), задаваемых на уровне описания таблиц и на уровне связей между таблицами. При написании триггеров всегда надо помнить об этом, при нарушении правил целостности по связям (DRI declarative Referential Integrity) триггер просто может никогда не сработать.
В стандарте SQL1 ни хранимые процедуры, ни триггеры были не определены. Но в добавлении к стандарту SQL2, выпущенному в 1996 году, те и другие объекты были стандартизированы и определены.
Для создания триггеров используется специальная команда:
CREATE TRIGGER
ON
FOR {[INSERT][. UPDATE] [. DELETE] }
[WITH ENCRIPTING]
271
AS
SQL-операторы (Тело триггера)
Имя триггера является идентификатором во встроенном языке программирования СУБД и должно удовлетворять соответствующим требованиям.
В параметре FOR задается одна или несколько операций модификации, которые запускают данный триггер.
Параметр WITH ENCRIPTING имеет тот же смысл, что и для хранимых процедур, он скрывает исходный текст тела триггера.
Существует несколько правил, которые ограничивают набор операторов, которые могут быть использованы в теле триггера.
Так, в большинстве СУБД действуют следующие ограничения:
Нельзя использовать в теле триггера операции создания объектов БД (новой БД, новой таблицы, нового индекса, новой хранимой процедуры, нового триггера, новых индексов, новых представлений).
Нельзя использовать в триггере команду удаления объектов DROP для всех типов базовых объектов БД.
Нельзя использовать в теле триггера команды изменения базовых объектов ALTER TABLE. ALTER DATABASE.
Нельзя изменять права доступа к объектам БД, то есть выполнять команду GRAND или REVOKE.
Нельзя создать триггер для представления (VIEW) .
В отличие от хранимых процедур, триггер не может возвращать никаких значений, он запускается автоматически сервером и не может связаться самостоятельно ни с одним клиентом.
Рассмотрим пример триггера, который срабатывает при удалении экземпляра некоторой книги, например, в случае утери этой книги читателем. Что же может делать этот триггер? А он может выполнять следующую проверку: проверять, остался ли еще хоть один экземпляр данной книги в библиотеке, и если это был последний экземпляр книги в библиотеке, то резонно удалить описание книги из предметного каталога, чтобы наши читатели зря не пытались заказать эту книгу.
Текст этого триггера на языке Transact SQL приведен ниже:
/* Проверка существования данного триггера в системном каталоге */
If exists (select * from sysobjects where id = object_id(?dbo.DEL_EXEMP?) and
sysstat & Oxf = 8)
drop trigger dbo.DEL_EXEMP
GO
CREATE TRIGGER DEL_EXEMP ON dbo.EXEMPLAR /* мы создаем триггер для таблицы
EXEMPLAR */
FOR DELETE /* только для операции удаления */
272
AS
/* опишем локальные переменные */
DECLARE @Ntek int /* количество оставшихся экземпляров удаленной книги */
DECLARE @DEL_EX VARCHAR(12) /* шифр удаленного экземпляра*/
Begin /* по временной системной таблице, содержащей удаленные записи,
определяем шифр книги, соответствующей последнему удаленному экземпляру */
SELECT @DEL_EX = ISBN From deleted
/* вызовем хранимую процедуру, которая определит количество экземпляров книги
с заданным шифром */
EXEC @Ntek = COUNT_EX @DEL_EX
/* Если больше нет экземпляров данной книги, то мы удаляем запись о книге из
таблицы BOOKS */
IF @Ntek = О DELETE from BOOKS WHERE BOOKS.ISBN = @DEL EXENDGO
Удаление и обновление данных с использованием курсора
Курсоры в прикладных программах часто используются для последовательного просмотра данных. Если курсор не связан с операцией группировки, то фактически каждая строка курсора соответствует строго только одной строке исходной таблицы, и в этом случае курсор удобно использовать для оперативной корректировки данных. В стандарте определены операции модификации данных, связанные с курсором. Операция удаления строки, связанной с текущим указателем курсора, имеет следующий синтаксис:
DELETE FROM WHERE CURRENT OF
Если указанный в операторе курсор открыт и установлен на некоторую строку, и курсор определяет изменяемую таблицу, то текущая строка курсора удаляется, а он позиционируется перед следующей строкой. Таблица, указанная в разделе FROM оператора DELETE, должна быть таблицей, указанной в самом внешнем разделе FROM спецификации курсора.
Если нам необходимо прочитать следующую строку курсора, то надо снова выполнить оператор FETCH NEXT.
Аналогично курсор может быть использован для модификации данных. Синтаксис операции позиционной модификации следующий:
UPDATE SET = { | NULL}
[{,= { | NULL}}...]
WHERE CURRENT OF
Одним оператором позиционного обновления могут быть заменены несколько значений столбцов строки таблицы, соответствующей текущей позиции курсора. После выполнения операции модификации позиция курсора не изменяется.
Для того чтобы можно было применять позиционные операторы удаления (DELETE) и модификации (UPDATE), курсор должен удовлетворять определенным требованиям. Согласно стандарту SQL1, это следующие требования:
257
Запрос, связанный с курсором, должен считывать данные из одной исходной таблицы, то есть в предложении FROM запроса SELECT, связанного с определением курсора (DECLARE CURSOR), должна быть задана только одна таблица.
В запросе не может присутствовать параметр упорядочения ORDER BY. Для того чтобы сохранялось взаимно однозначное соответствие строк курсора и исходной таблицы, курсор не должен идентифицировать упорядоченный набор данных.
В запросе не должно присутствовать ключевое слово DISTINCT.
Запрос не должен содержать операций группировки, то есть в нем не должно присутствовать предложение GROUP BY или HAVING.
Пользователь, который хочет применить операции позиционного удаления или обновления, должен иметь соответствующие права на выполнение данных операций над базовой таблицей. (О правах и привилегиях пользователя мы поговорим в главе 13.)
Использование курсора для операций обновления значительно усложняет работу с подобным курсором со стороны СУБД, поэтому операции, связанные с позиционной модификацией, выполняются гораздо медленнее, чем операции с курсорами, которые используются только для чтения. Именно поэтому рекомендуется обязательно указывать в операторе определения курсора предложение READ ONLY, если вы не собираетесь использовать данный курсор для операций модификации. По умолчанию, если нет дополнительных указаний, СУБД создает курсор с возможностью модификации.
Курсоры - удобное средство для формирования бизнес - логики приложений, но следует помнить, что если вы открываете курсор с возможностью модификации, то СУБД блокирует все строки базовой таблицы, вошедшие в ваш курсор, и тем самым блокируется работа других пользователей с данной таблицей.
Чтобы свести к минимуму количество требуемых блокировок, при работе интерактивных программ следует придерживаться следующих правил:
Необходимо делать транзакции как можно короче.
Необходимо выполнять оператор завершения COMMIT после каждого запроса и как можно скорее после изменений, сделанных программой.
Необходимо избегать программ, в которых осуществляется интенсивное взаимодействие с пользователем или осуществляется просмотр очень большого количества строк данных.
Если возможно, то лучше не применять прокручиваемые курсоры (SCROLL), потому что они требуют блокирования всех строк выборки, связанных с открытым курсором.
Использование простого последовательного курсора позволит системе разблокировать текущую строку, как только будет выполнена операция FETCH, что минимизирует блокировки других пользователей, работающих параллельно с вами и использующих те же таблицы.
Если возможно, определяйте курсор как READ ONLY.
258
Однако когда мы рассматривали модели "клиент - сервер", применяемые в БД, то определили, что в развитых моделях серверов баз данных большая часть бизнес - логики клиентского приложения выполняется именно на сервере, а не на клиенте. Для этого используются специальные объекты, которые называются хранимыми процедурами и хранятся в БД, как таблицы и другие базовые объекты.
В связи с этим фактом курсоры, которые могут быть использованы в приложениях, обычно делятся на курсоры сервера и курсоры клиента. Курсор сервера создается и выполняется на сервере, данные, связанные с ним, не пересылаются на компьютер клиента. Курсоры сервера определяются обычно в хранимых процедурах или триггерах.
Курсоры клиента - это те курсоры, которые определяются в прикладных программах, выполняемых на клиенте. Набор строк, связанный с данным курсором, пересылается на клиент и там обрабатывается. Если с курсором связан большой набор данных, то операция пересылки набора строк, связанных с курсором, может занять значительное время и значительные ресурсы сети и клиентского компьютера.
Конечно, курсоры сервера более экономичны и выполняются быстрее. Поэтому последней рекомендацией, связанной с использованием курсоров, будет рекомендация трансформировать логику работы вашего приложения, чтобы как можно чаще вместо курсоров клиента использовать курсоры сервера.
Уровни изолированности пользователей
Достаточно легко убедиться, что при соблюдении двухфазного протокола синхронизационных захватов действительно обеспечивается полная сериализация транзакций. Однако иногда приложению, которое выполняет транзакцию, не сколько важны точные данные, сколько скорость выполнения запросов. Например, в системах поддержки принятия решений по электронным торгам важно просто иметь представление об общей картине торгов, на основании которого принимается решение об повышении или снижении ставок и т. д. Для смягчения требований сериализации транзакций вводится понятие уровня изолированности пользователя.
Уровни изолированности пользователей связаны с проблемами, которые возникают при параллельном выполнении транзакций и которые были рассмотрены нами ранее.
Всего введено 4 уровня изолированности пользователей. Самый высокий уровень изолированности соответствует протоколу сериализации транзакций, это уровень SERIALIZABLE. Этот уровень обеспечивает полную изоляцию транзакций и полную корректную обработку параллельных транзакций.
Следующий уровень изолированности называется уровнем подтвержденного чтения - REPEATABLE READ. На этом уровне транзакция не имеет доступа к промежуточным или окончательным результатам других транзакций, поэтому такие проблемы, как пропавшие обновления, промежуточные или несогласованные данные, возникнуть не могут. Однако во время выполнения своей транзакции вы можете увидеть строку, добавленную в БД другой Транзакцией. Поэтому один и тот же запрос, выполненный в течение одной транзакции, может дать разные результаты, то есть проблема строк-призраков остается. Однако если такая проблема критична, лучше ее разрешать алгоритмически, изменяя алгоритм обработки, исключая повторное выполнение запроса в одной транзакции.
Второй уровень изолированности связан с подтвержденным чтением, он называется READ COMMITED. На этом уровне изолированности транзакция не имеет доступа к промежуточным результатам других транзакций, поэтому проблемы пропавших обновлений и промежуточных данных возникнуть не могут.
Однако окончательные данные, полученные в ходе выполнения других транзакций, могут быть доступны нашей транзакции. При этом уровне изолированности транзакция не может обновлять строку, уже обновленную другой транзакцией. При попытке выполнить подобное обновление транзакция будет отменена автоматически, во избежание возникновения проблемы пропавшего обновления.
И наконец, самый низкий уровень изолированности называется уровнем неподтвержденного, или грязного, чтения. Он обозначается как READ UNCOMMITED. При этом уровне изолированности текущая транзакция видит промежуточные и несогласованные данные, и также ей доступны строки-призраки. Однако даже при этом уровне изолированности СУБД предотвращает пропавшие обновления.
В стандарте SQL2 существует оператор задания уровня изолированности выполнения транзакции. Он имеет следующий синтаксис:
241
SET TRANSACTION IZOLATION LEVEL [{SERIALIZABLE |
REPEATABLE READ |
READ COMMITED |
READ UNCOMMITED}] [{READ WRITE |
READ ONLY }]
Дополнительно в этом операторе может быть указано, операции какого типа выполняются в транзакции. По умолчанию предполагается уровень SERIALIZABLE. Если задан уровень READ UNCOMMITED, то допустимы только операции чтения в транзакции, поэтому в этом случае нельзя установить операции READ WRITE. На рис. 11.11 приведено соответствие уровней изолированности транзакций и проблем, возникающих при параллельном выполнении транзакций.
Уровень изоляции | Появление пропавших обновлений | Появление промежуточных данных | Появление несогласованных данных | Появление строк - призраков |
SERIALIZABLE | СУБД предотвращает | СУБД предотвращает | СУБД предотвращает | СУБД предотвращает |
REPEATABLE READ | СУБД предотвращает | СУБД предотвращает | СУБД предотвращает | Может произойти |
READ COMMITED | СУБД предотвращает | СУБД предотвращает | Может произойти | Может произойти |
READ UNCOMMITED | СУБД предотвращает | Может произойти | Может произойти | Может произойти |
В разных коммерческих СУБД могут быть реализованы не все уровни изолированности, это необходимо выяснить в технической документации.
Вертикальное представление
Этот вид представления практически соответствует выполнению операции проектирования некоторого отношения на ряд столбцов. Он используется в основном для скрытия информации, которая не должна быть доступна в конкретной внешней модели.
Например, для работника табельной службы, который учитывает присутствие сотрудников на работе, информация об окладе и надбавке должна быть закрыта. Для него можно создать следующее вертикальное представление:
CREATE VIEW TABEL
AS
SELECT T_NUM.NAME. POSITION. DEPARTMENT
FROM EMPLOYEE
159
159 :: Содержание
Вложенные запросы
Теперь вернемся к БД "Сессия" и рассмотрим на ее примере использование вложенных запросов.
С помощью SQL можно вкладывать запросы внутрь друг друга. Обычно внутренний запрос генерирует значение, которое проверяется в предикате внешнего запроса (в предложении WHERE или HAVING), определяющего, верно оно или нет. Совместно с подзапросом можно использовать предикат EXISTS, который возвращает истину, если вывод подзапроса не пуст,
В сочетании с другими возможностями оператора выбора, такими как группировка, подзапрос представляет собой мощное средство для достижения нужного результата. В части FROM оператора SELECT допустимо применять синонимы к именам таблицы, если при формировании запроса нам требуется более чем один экземпляр некоторого отношения. Синонимы задаются с использованием ключевого слова AS, которое может быть вообще опущено. Поэтому часть FROM может выглядеть следующим образом:
FROM R1 AS A. R1 AS В
или
FROM R1 A. R1 В;
оба выражения эквивалентны и рассматриваются как применения оператора SELECT к двум экземплярам таблицы R1.
Например, покажем, как выглядят на SQL некоторые запросы к БД "Сессия":
Список тех, кто сдал все положенные экзамены.
SELECT ФИО
FROM R1 as a
WHERE Оценка > 2
GROUP BY ФИО
HAVING COUNT(*) = (SELECT COUNT(*)
87
FROM R2.R3
WHERE R2.rpynna=R3.Группа AND ФИО=а.ФИО)
Здесь во встроенном запросе определяется общее число экзаменов, которые должен сдавать каждый студент, обучающийся в группе, в которой учится данный студент, и это число сравнивается с числом экзаменов, которые сдал данный студент.
Список тех, кто должен был сдавать экзамен по БД, но пока еще не сдавал.
SELECT ФИО
FROM R2 a. R3
WHERE R2.Группа = R3.Группа AND Дисциплина = "БД" AND NOT EXISTS (SELECT ФИО
FROM R1
WHERE ФИО=а.ФИО AND Дисциплина - "БД")
Предикат EXISTS ( SubQuery) истинен, когда подзапрос SubQuery не пуст, то есть содержит хотя бы один кортеж, в противном случае предикат EXISTS ложен.
Предикат NOT EXISTS обратно - истинен только тогда, когда подзапрос SubQuery пуст.
Обратите внимание, каким образом NOT EXISTS с вложенным запросом позволяет обойтись без операции разности отношений. Например, формулировка запроса со словом "все" может быть выполнена как бы с двойным отрицанием. Рассмотрим пример базы, которая моделирует поставку отдельных деталей отдельными поставщиками, она представлена одним отношением SP "Поставщики-детали" со схемой
SP (Номер_поставщика. номер_детали)
Р (номер_детали. наименование)
Вот каким образом формулируется ответ на запрос: "Найти поставщиков, которые поставляют все детали".
SELECT DISTINCT НОМЕР_ПОСТАВЩИКА
FROM SP SP1
WHERE NOT EXISTS
(SELECT номер_детали
FROM P
WHERE NOT EXISTS
(SELECT * FROM SP SP2
WHERE SР2.номер_поставщика=SР1.номер_поставщика AND
sр2.номер_детали = Р.номер_детали));
Фактически мы переформулировали этот запрос так: "Найти поставщиков таких, что не существует детали, которую бы они не поставляли". Следует отметить, что этот запрос может быть реализован и через агрегатные функции с подзапросом:
88
SELECT DISTINCT Номер_поставщика
FROM SP
GROUP BY Номер_поставщика
HAVING Count(DISTINCT номер_детали) =
(SELECT Count( номер_детали)
FROM P)
В стандарте SQL92 операторы сравнения расширены до многократных сравнений с использованием ключевых слов ANY и ALL. Это расширение используется при сравнении значения определенного столбца со столбцом данных, возвращаемым вложенным запросом.
Ключевое слово ANY, поставленное в любом предикате сравнения, означает, что предикат будет истинен, если хотя бы для одного значения из подзапроса предикат сравнения истинен. Ключевое слово ALL требует, чтобы предикат сравнения был бы истинен при сравнении со всеми строками подзапроса.
Например, найдем студентов, которые сдали все экзамены на оценку не ниже чем "хорошо". Работаем с той же базой "Сессия", но добавим к ней еще одно отношение R4, которое характеризует сдачу лабораторных работ в течение семестра:
R1 = (ФИО, Дисциплина, Оценка);
R2 = (ФИО, Группа);
R3 = (Группы, Дисциплина )
R4 = (ФИО, Дисциплина, Номер_лаб_раб, Оценка);
Select R1.ФИО
From R1
Where 4 > = All (Select R1.Оценка
From R1 as R11
Where R1.Фио = R11.Фио)
Рассмотрим еще один пример:
Выбрать студентов, у которых оценка по экзамену не меньше, чем хотя бы одна оценка по сданным им лабораторным работам по данной дисциплины:
Select R1.Фио
From R1
Where R1.Оценка >= ANY (Select Р4.Оценка
From R4
Where R1.Дисциплина = R4: Дисциплина AND R1.Фио = Р4.Фио)
Внешние модели
При работе с иерархической моделью каждая программа, пользователь или приложение определяет свою внешнюю модель. Внешняя модель представляет собой совокупность поддеревьев для физических баз данных, с которыми работает данный пользователь. Каждый подграф внешней модели в обязательном порядке должен содержать корневой тип сегмента соответствующей физической базы данных концептуальной модели.
35
Представление внешней модели называется логической базой данных и определяется совокупностью блоков связи данного приложения с физическими БД, входящими в концептуальную схему БД. Блок связи - PCB, program communication bloc - описывает связь с одной физической БД по следующим правилам:
DBD NAME - < имя логической БД (подсхемы)> , ACCESS = LOGICAL
DATA SET = LOGICAL.
SEGM NAME = . PARENT =, SOURSE =(Имя соответствующего сегмента ФБД. имя ФБД)
...
DBDGEN
FINISH
END
Совокупность блоков PCB образует полное внешнее представление данного приложения, называемое "блоком спецификации программ" (PSB, program specification block).
Рассмотрим пример иерархической БД.
Наша организация занимается производством и продажей компьютеров, в рамках производства мы комплектуем компьютеры из готовых деталей по индивидуальным заказам. У нас существует несколько базовых моделей, которые мы продаем без предварительных заказов по наличию на складе. В организации существуют несколько филиалов (рис. 3.4) и несколько складов, на которых хранятся комплектующие. Нам необходимо вести учет продаваемой продукции.
Рис. 3.4. Физическая БД "Филиалы"
Какие задачи нам надо решать в ходе разработки приложения?
При приеме заказа мы должны выяснить, какую модель заказывает заказчик: типичную или индивидуальную комплектацию.
Если заказывается типичная модель, то выясняется, какая модель и есть ли она в наличии, если модель есть, то надо уменьшить количество компьютеров данной модели в данном филиале на покупаемое количество. На этом будем считать заказ выполненным, однако при оформлении заказа может потребоваться задание полной спецификации покупаемого изделия.
36
Если заказывается индивидуальная модель, то требуется описать весь состав новой модели.
Для того чтобы можно было бы принимать заказы на индивидуальные модели, нам понадобится информация о наличие конкретных деталей на складе, в этом случае нам необходимо второе дерево - Склады (см. рис. 3.5).
Рис. 3.5. Физическая модель "Склады"
37
34 :: 35 :: 36 :: 37 :: Содержание
Внешние объединения
Стандарт SQL2 расширил понятие условного объединения. В стандарте SQL1 при объединении отношений использовались только условия, задаваемые в части
89
WHERE оператора SELECT, и в этом случае в результирующее отношение попадали только сцепленные по заданным условиям кортежи исходных отношений, для которых эти условия были определены и истинны. Однако в действительности часто необходимо объединять таблицы таким образом, чтобы в результат попали все строки из первой таблицы, а вместо тех строк второй таблицы, для которых не выполнено условие соединения, в результат попадали бы неопределенные значения. Или наоборот, включаются все строки из правой (второй) таблицы, а отсутствующие части строк из первой таблицы дополняются неопределенными значениями. Такие объединения были названы внешними в противоположность объединениям, определенным стандартом SQL1, которые стали называться внутренними.
В общем случае синтаксис части FROM в стандарте SQL2 выглядит следующим образом:
FROM |
< выражение естественного объединения > |
< выражение объединения > |
< выражение перекрестного объединения > |
< выражение запроса на объединение >
::= [ имя синонима таблицы_1] [ ...]
[[ ] ]
:: =
NATURAL { INNER | FULL [OUTER] |
LEFT [OUTER] | RIGHT [OUTER]} JOIN
CROSS JOIN
UNION JOIN
{ INNER |
FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER]}
JOIN {ON условие | [USING (список столбцов)]}
В этих определениях INNER - означает внутреннее объединение, LEFT - левое объединение, то есть в результат входят все строки таблицы 1, а части результирующих кортежей, для которых не было соответствующих значений в таблице 2, дополняются значениями NULL (неопределено). Ключевое слово RIGHT означает правое внешнее объединение, и в отличие от левого объединения в этом случае в результирующее отношение включаются все строки таблицы 2, а недостающие части из таблицы 1 дополняются неопределенными значениями, Ключевое слово FULL определяет полное внешнее объединение: и левое и правое.
При полном внешнем объединении выполняются и правое и левое внешние объединения и в результирующее отношение включаются все строки из таблицы 1, дополненные неопределенными значениями, и все строки из таблицы 2, также дополненные неопределенными значениями.
90
Ключевое слово OUTER означает внешнее, но если заданы ключевые слова FULL, LEFT, RIGHT, то объединение всегда считается внешним.
Рассмотрим примеры выполнения внешних объединений. Снова вернемся к БД "Сессия". Создадим отношение, в котором будут стоять все оценки, полученные всеми студентами по всем экзаменам, которые они должны были сдавать. Если студент не сдавал данного экзамена, то вместо оценки у него будет стоять неопределенное значение. Для этого выполним последовательно естественное внутреннее объединение таблиц R2 и R3 по атрибуту Группа, а полученное отношение соединим левым внешним естественным объединением с таблицей R1, используя столбцы ФИО и Дисциплина. При этом в стандарте разрешено использовать скобочную структуру, так как результат объединения может быть одним из аргументов в части FROM оператора SELECT.
SELECT R1.ФИО. R1.Дисциплина. R1.Оценка
FROM (R2 NATURAL INNER JOIN R3 ) LEFT JOIN Rl USING ( ФИО. Дисциплина)
Результат:
ФИО | Дисциплина | Оценка |
Петров Ф. И. | Базы данных | 5 |
Сидоров К. А. | Базы данных | 4 |
Сидоров К. А. | Базы данных | 4 |
Миронов А. В. | Базы данных | 2 |
Степанова К. Е. | Базы данных | 2 |
Крылова Т. С. | Базы данных | 5 |
Владимиров В. А. | Базы данных | 5 |
Петров Ф. И. | Теория информации | Null |
Сидоров К. А. | Теория информации | 4 |
Миронов А. В. | Теория информации | Null |
Степанова К. Е. | Теория информации | 2 |
Крылова Т. С. | Теория информации | 5 |
Владимиров В. А. | Теория информации | Null |
Петров Ф. И. | Английский язык | 5 |
Сидоров К. А. | Английский язык | Null |
Миронов А. В. | Английский язык | Null |
Степанова К. Е. | Английский язык | Null |
Крылова Т. С. | Английский язык | Null |
Владимиров В. А. | Английский язык | 4 |
Трофимов П. А. | Сети и телекоммуникации | 4 |
Иванова Е. А. | Сети и телекоммуникации | 5 |
91
ФИО | Дисциплина | Оценка |
Уткина Н. В. | Сети и телекоммуникации | 5 |
Трофимов П. А. | Английский язык | 5 |
Иванова Е. А. | Английский язык | 3 |
Уткина Н. В. | Английский язык | Null |
BOOKS(ISBN. TITL. AUTOR. COAUTOR. YEARIZD. PAGES)
READER(NUM_READER, NAME_READER, ADRESS. HOOM_PHONE. WORK_PHONE. BIRTH_DAY)
EXEMPLAREUNV. ISBN. YES_NO. NUM_READER. DATEJN. DATE_OUT)
Здесь таблица BOOKS описывает все книги, присутствующие в библиотеке, она имеет следующие атрибуты:
ISBN - уникальный шифр книги;
TITL - название книги;
AUTOR - фамилия автора;
COAUTOR - фамилия соавтора;
YEARIZD - год издания;
PAGES - число страниц.
Таблица READER хранит сведения обо всех читателях библиотеки, и она содержит следующие атрибуты:
NUM_READER - уникальный номер читательского билета;
NAME_READER - фамилию и инициалы читателя;
ADRESS - адрес читателя;
HOOM_PHONE - номер домашнего телефона;
WORK_PHONE - номер рабочего телефона;
BIRTH_DAY - дату рождения читателя.
Таблица EXEMPLARE содержит сведения о текущем состоянии всех экземпляров всех книг. Она включает в себя следующие столбцы:
INV - уникальный инвентарный номер экземпляра книги;
ISBN - шифр книги, который определяет, какая это книга, и ссылается на сведения из первой таблицы;
YES_NO - признак наличия или отсутствия в библиотеке данного экземпляра в текущий момент;
NUM_READER - номер читательского билета, если книга выдана читателю, и Null в противном случае;
92
DATE_IN - если книга у читателя, то это дата, когда она выдана читателю;
DATE_OUT - дата, когда читатель должен вернуть книгу в библиотеку.
Определим перечень книг у каждого читателя; если у читателя нет книг, то номер экземпляра книги равен NULL. Для выполнения этого поиска нам надо использовать левое внешнее объединение, то есть мы берем все строки из таблицы READER и соединяем со строками из таблицы EXEMPLARE, если во второй таблице нет строки с соответствующим номером читательского билета, то в строке результирующего отношения атрибут EXEMPLARE.INV будет иметь неопределенное значение NULL:
SELECT READER.NAME_READER, EXEMPLARE.INV
FROM READER RIGHT JOIN EXEMPLARE ON READER.NUM_READER=EXEMPLARE.NUM_READER
Операция внешнего объединения, как мы уже упоминали, может использоваться для формирования источников в предложении FROM, поэтому допустимым будет, например, следующий текст запроса:
SELECT *
FROM ( BOOKS LEFT JOIN EXEMPLARE)
LEFT JOIN
(READER NATURAL JOIN EXEMPLARE)
USING (ISBN)
При этом для книг, ни один экземпляр которых не находится на руках у читателей, значения номера читательского билета и дат взятия и возврата книги будут неопределенными.
Перекрестное объединение в трактовке стандарта SQL2 соответствует операции расширенного декартова произведения, то есть операции соединения двух таблиц, при которой каждая строка первой таблицы соединяется с каждой строкой второй таблицы.
Операция запроса на объединение эквивалентна операции теоретико-множественного объединения в алгебре. При этом требование эквивалентности схем исходных отношений сохраняется. Запрос на объединение выполняется по следующей схеме:
SELECT - запрос
UNION
SELECT - запрос
UNION
SELECT - запрос
Все запросы, участвующие в операции объединения, не должны содержать выражений, то есть вычисляемых полей.
Например, нужно вывести список читателей, которые держат на руках книгу "Идиот" или книгу "Преступление и наказание". Вот как будет выглядеть запрос:
93
SELECT READER. NAMEJEADER
FROM READER. EXEMPLARE.BOOKS
WHERE EXEMPLARE.NUM_READER= READER.NUM_READER AND
EXEMPLRE.ISBN = BOOKS.ISBN AND
BOOKS.TITLE = "Идиот"
UNION
SELECT READER NAME_READER
FROM READER, EXEMPLARE.BOOKS
WHERE EXEMPLARE.NUM_READER= READER. NUMJEADER AND
EXEMPLRE.ISBN = BOOKS.ISBN AND
BOOKS.TITLE = "Преступление и наказание"
По умолчанию при выполнении запроса на объединение дубликаты кортежей всегда исключаются. Поэтому, если найдутся читатели, у которых находятся на руках обе книги, то они все равно в результирующий список попадут только один раз.
Запрос на объединение может объединять любое число исходных запросов.
Так, к предыдущему запросу можно добавить еще читателей, которые держат на руках книгу "Замок":
UNION
SELECT READER. NAME_READER
FROM READER. EXEMPLARE.BOOKS
WHERE EXEMPLARE.NUM_READER= READER.NUM_READER AND
EXEMPLRE.ISBN - BOOKS.ISBN AND
BOOKS.TITLE - "Замок"
В том случае, когда вам необходимо сохранить все строки из исходных отношений, необходимо использовать ключевое слово ALL в операции объединения. В случае сохранения дубликатов кортежей схема выполнения запроса на объединение будет выглядеть следующим образом:
SELECT - запрос
UNION ALL
SELECT - запрос
UNION ALL
SELECT - запрос
Однако тот же результат можно получить простым изменением фразы WHERE первой части исходного запроса, соединив локальные условия логической операцией ИЛИ и исключив дубликаты кортежей.
SELECT DISTINCT READER.NAME_READER
FROM READER. EXEMPLARE.BOOKS
94
WHERE EXEMPLARE.NUM_READER= READER.NUM_READER AND
EXEMPLRE.ISBN = BOOKS.ISBN AND
BOOKS.TITLE = "Идиот" OR
BOOKS.TITLE = "Преступление и наказание" OR
BOOKS.TITLE = "Замок"
Ни один из исходных запросов в операции UNION не должен содержать предложения упорядочения результата ORDER BY, однако результат объединения может быть упорядочен, для этого предложение ORDER BY с указанием списка столбцов упорядочения записывается после текста последнего исходного SELECT-запроса.
Вопросы для самостоятельной работы
Сравнить обе стратегии и определить, какая из них будет наиболее перспективной и в каких случаях.
Разработать алгоритмы удаления записей для первой и второй стратегий. Показать, как определяются ссылки.
169
169 :: Содержание
Восстановление после мягкого сбоя
К числу основных проблем восстановления после мягкого сбоя относится то, что одна логическая операция изменения базы данных может изменять несколько физических блоков базы данных, например, страницу данных и несколько страниц индексов. Страницы базы данных буферизуются в оперативной памяти и выталкиваются независимо. Несмотря на применение протокола WAL, после мягкого сбоя набор страниц внешней памяти базы данных может оказаться несогласованным, то есть часть страниц внешней памяти соответствует объекту до изменения, часть - после изменения. К такому состоянию объекта неприменимы операции логического уровня.
Состояние внешней памяти базы данных называется физически согласованным, если наборы страниц всех объектов согласованы, то есть соответствуют состоянию объекта либо до его изменения, либо после изменения.
Будем считать, что в журнале отмечаются точки физической согласованности базы данных - моменты времени, в которые во внешней памяти содержатся согласованные результаты операций, завершившихся до соответствующего момента времени, и отсутствуют результаты операций, которые не завершились, а буфер журнала вытолкнут во внешнюю память. Немного позже мы рассмотрим, как можно достичь физической согласованности. Назовем такие точки tpc (time of physical consistency) - точками физического согласования.
Тогда к моменту мягкого сбоя возможны следующие состояния транзакций:
транзакция успешно завершена, то есть выполнена операция подтверждения транзакции COMMIT и для всех операций транзакции получено подтверждение ее выполнения во внешней памяти;
транзакция успешно завершена, но для некоторых операций не получено подтверждение их выполнения во внешней памяти;
транзакция получила и выполнила команду отката ROLLBACK;
транзакция не завершена.
227
227 :: Содержание
Восстановление после жесткого сбоя
Понятно, что для восстановления последнего согласованного состояния базы данных после жесткого сбоя журнала изменений базы данных явно недостаточно. Основой восстановления в этом случае являются журнал и архивная копия базы данных.
Восстановление начинается с обратного копирования базы данных из архивной копии. Затем для всех закончившихся транзакций выполняется redo, то есть операции повторно выполняются в прямом порядке.
Более точно, происходит следующее:
по журналу в прямом направлении выполняются все операции;
для транзакций, которые не закончились к моменту сбоя, выполняется откат.
На самом деле, поскольку жесткий сбой не сопровождается утратой буферов оперативной памяти, можно восстановить базу данных до такого уровня, чтобы можно было продолжить даже выполнение незакончившихся транзакций. Но обычно это не делается, потому что восстановление после жесткого сбоя - это достаточно длительный процесс.
Хотя к ведению журнала предъявляются особые требования по части надежности, в принципе возможна и его утрата. Тогда единственным способом восстановления базы данных является возврат к архивной копии. Конечно, в этом случае не удастся получить последнее согласованное состояние базы данных, но это лучше, чем ничего.
Последний вопрос, который мы коротко рассмотрим, относится к производству архивных копий базы данных. Самый простой способ - архивировать базу данных при переполнении журнала. В журнале вводится так называемая "желтая зона", при достижении которой образование новых транзакций временно блокируется. Когда все транзакции закончатся и, следовательно, база данных придет в согласованное состояние, можно производить ее архивацию, после чего начинать заполнять журнал заново.
Можно выполнять архивацию базы данных реже, чем переполняется журнал. При переполнении журнала и окончании всех начатых транзакций можно архивировать сам журнал. Поскольку такой архивированный журнал, по сути дела, требуется только для воссоздания архивной копии базы данных, журнальная информация при архивации может быть существенно сжата.
230
230 :: Содержание
Задание для самостоятельной работы
Разработать алгоритмы добавления записи для всех трех случаев
Однако часто бывает необходимо просматривать цепочку подчиненных записей в двух направлениях: прямом и обратном. В этом случае применяют двойные указатели.
В "основном файле" один указатель равен номеру первой записи в цепочке записей "подчиненного файла", а второй - номеру последней записи.
В "подчиненном файле" один указатель равен номеру следующей записи в цепочке, а другой - номеру предыдущей записи в цепочке. Для первой и последней записей в цепочке один из указателей пуст, то есть равен пробелу.
Для нашего примера это выглядит следующим образом:
F1 | |||
Номер записи | Ключ и остальная запись | Указатель на первую запись | Указатель на последнюю запись |
1 | Иванов И. Н ..... | 1 | 5 |
2 | Петров А. А. | 3 | 6 |
3 | Сидоров П. А. | 2 | 2 |
4 | Яковлев В. В. |
F2 | |||
Номер записи | Указатель на предыдущую запись в цепочке | Указатель на следующую запись в цепочке | Содержимое записи |
1 | - | 4 | 4306 Вычислительные сети |
2 | - | - | 4307 Контроль и диагностика |
3 | - | 6 | 4308 Вычислительные сети |
4 | 1 | 5 | 84305 Моделирование |
5 | 4 | - | 4309 Вычислительные сети |
6 | 3 | - | 84405 Техническая диагностика |
7 | - |
181
Один файл ("подчиненный" или "основной") может быть связан с несколькими другими файлами, при этом для каждой связи моделируются свои указатели. Связь двух основных файлов F1 и F2 с одним связующим файлом F3 моделируется на
|
|
F3 | ||
Цепочки для файла F1 | Содержимое записи | Цепочки для файла F2 |
182
178 :: 179 :: 180 :: 181 :: 182 :: Содержание
Задания для самостоятельной работы
Задание 1
Даны отношения, моделирующие работу банка и его филиалов. Клиент может иметь несколько счетов, при этом они могут быть размещены как в Одном, так и в разных филиалах банка. В отношении R1 содержится информация обо всех клиентах и их счетах в филиалах нашего банка. Каждый клиент, в соответствии со своим счетом, может рассчитывать на некоторый кредит от нашего банка, сумма допустимого кредита также зафиксирована.
R1 | ||||
ФИО клиента | № филиала | № счета | Остаток | Кредит |
R2 | |
№ филиала | Район |
С использованием языка реляционной алгебры составить запросы, позволяющие выбрать:
Филиалы, клиенты которых имеют счета с остатком, превышающим $1000.
Клиентов, которые имеют счета во всех филиалах данного банка.
Клиентов, которые имеют только по одному счету в разных филиалах банка. То есть в общем у этих клиентов может быть несколько счетов, но в одном филиале не более одного счета.
Клиенты, которые имеют счета в нескольких филиалах банка, расположенных только в одном районе.
Филиалы, которые не имеют ни одного клиента.
Филиалы, которые имеют клиентов с остатком на счету 0 (ноль).
63
Филиалы, у которых есть клиенты с кредитом, превышающим остаток на счету в 2 раза.
Задание 2
Даны отношения, моделирующие работу международной фирмы, имеющей несколько филиалов. Филиалы фирмы могут быть расположены в разных странах, это отражено в отношении R1. Клиенты фирмы также могут быть из разных стран, и это отражено в отношении R4. По каждому конкретному заказу клиент мог заказать несколько разных товаров.
R1 | |
Филиал | Страна |
R2 | ||
Филиал | Заказчик | № заказа |
R3 | ||
N заказа | Товар | Количество |
R4 | |
Заказчик | Страна |
С использованием реляционной алгебры составить запросы, позволяющие выбрать:
Заказчиков, которые работают со всеми филиалами фирмы, но покупают только один товар.
Филиалы фирмы, которые торгуют всеми товарами.
Товары, которые фирма продает только в одной стране.
В отношении R5 отметить студентов
Задание 1. В отношении R5 отметить студентов - претендентов на отчисление. Считаем, что в отношении R1 находятся окончательные результаты сессии, и поэтому отчислению подлежат все студенты, которые не сдали или не сдавали два и более из положенных экзаменов в сессию. Для того чтобы зафиксировать этот факт, нам потребуется добавить еще один столбец в отношение R5, назовем его результат_сессии, и там могут быть два допустимых значения: переведен на следующий курс или отчислен. Запрос писать по универсальному алгоритму.
Задание 2. В отношении R5 отметить студентов, переведенных на следующий курс.
Задание 3. Провести отчисление студентов по результатам текущей сессии. Обратите внимание, что это уже другая операция по сравнению с заданиями 1 и 2.
103
103 :: Содержание
с филиалами фирмы, которые расположены
Заказчиков, которые работают с филиалами фирмы, которые расположены только в одной стране.
Филиалы, с которыми не работает ни один заказчик.
Заказчиков, которые работают только с филиалами, расположенными в той же стране, что и заказчик.
Заказчиков, которые покупают все товары, представленные в отношении R3.
64
Задание 3
Даны отношения, моделирующие работу фирмы, занимающейся разработкой программных систем. Каждый сотрудник административно закреплен только за одним отделом. Файлы хранятся на разных серверах. На разных серверах файлы могут иметь одинаковые имена. Создатель файла является его владельцем, поэтому у каждого файла только один владелец, но владелец файла может разрешить пользоваться файлом другим сотрудникам. Существует множество системного программного обеспечения, каждая программа может работать с одним или с несколькими файлами, расположенными на одном или нескольких серверах:
|
|
R2 | ||
Название программы | Название файла | Сервер |
R3 | |
Название файла | Название сервера |
С использованием реляционной алгебры и языка составить запросы, позволяющие выбрать:
Файлы, которые имеют нескольких пользователей из разных отделов.
Программы, которые работают только с одним файлом.
Файлы, которые имеют одно и тоже имя, но расположены на различных серверах и используются сотрудниками разных отделов.
Файлы, с которыми работают сотрудники всех отделов.
Файлы, пользователями которых являются сотрудники только одного отдела.
Программы, которые работают со всеми серверами.
Отделы, сотрудники которых не работают ни с одним файлом. То есть отделы, в которых нет ни одного сотрудника, работающего с каким-нибудь файлом.
Отделы, сотрудники которых работают со всеми серверами.
Серверы, с которыми работают сотрудники только одного отдела.
65
63 :: 64 :: 65 :: Содержание
Перспективы развития БД и СУБД
Современные базы данных являются основой многочисленных информационных систем. Информация, накопленная в них, является чрезвычайно ценным материалом, и в настоящий момент широко распространяются методы обработки баз данных с точки зрения извлечения из них дополнительных знаний, методов, которые связаны с обобщением и различными дополнительными способами обработки данных. Базы данных в данной концепции выступают как хранилища информации, это направление называется "Хранилища данных" (Data Warehouse).
Для работы с "Хранилищами данных" наиболее значимым становится так называемый интеллектуальный анализ данных (ИАД), или data mining, - это процесс выявления значимых корреляций, образцов и тенденций в больших объемах данных. Учитывая высокие темпы роста объемов накопленной в современных хранилищах данных информации, невозможно недооценить роль ИАД. По мнению специалистов Gartner Group, уже в 1998 г. ИАД вошел в десятку важнейших информационных технологий. В последние годы началось активное внедрение технологии ИАД. Ее активно используют как крупные корпорации, так и более мелкие фирмы, которые серьезно относятся к вопросам анализа и прогнозирования своей деятельности. Естественно, на рынке программных продуктов стали появляться соответствующие инструментальные средства.
Особенно широко методы ИАД применяются в бизнес-приложениях аналитиками и руководителями компаний. Для этих категорий пользователей разрабатываются инструментальные средства высокого уровня, позволяющие решать достаточно сложные практические задачи без специальной математической подготовки. Актуальность использования ИАД в бизнесе связана с жесткой конкуренцией, возникшей вследствие перехода от "рынка продавца" к "рынку покупателя". В этих условиях особенно важно качество и обоснованность принимаемых решений, что требует строгого количественного анализа имеющихся данных. При работе с большими объемами накапливаемой информации необходимо постоянно оперативно отслеживать динамику рынка, а это практически невозможно без автоматизации аналитической деятельности.
приложениях наибольший интерес представляет интеграция
295
В бизнес - приложениях наибольший интерес представляет интеграция методов интеллектуального анализа данных с технологией оперативной аналитической обработки данных (On-Line Analytical Processing, OLAP). OLAP использует многомерное представление агрегированных данных для быстрого доступа к важной информации и дальнейшего ее анализа.
Системы OLAP обеспечивают аналитикам и руководителям быстрый последовательный интерактивный доступ к внутренней структуре данных и возможность преобразования исходных данных с тем, чтобы они позволяли отразить структуру системы нужным для пользователя способом. Кроме того, OLAP - системы позволяют просматривать данные и выявлять имеющиеся в них закономерности либо визуально, либо простейшими методами (такими как линейная регрессия), а включение в их арсенал нейросетевых методов обеспечивает существенное расширение аналитических возможностей.
В основе концепции оперативной аналитической обработки (OLAP) лежит многомерное представление данных. Термин OLAP ввел Кода (Е. F. Codd) в 1993 году. В своей статье он рассмотрел недостатки реляционной модели, в первую очередь невозможность "объединять, просматривать и анализировать данные с точки зрения множественности измерений, то есть самым понятным для корпоративных аналитиков способом", и определил общие требования к системам OLAP, расширяющим функциональность реляционных СУБД и включающим многомерный анализ как одну из своих характеристик.
Следует заметить, что Кодд обозначает термином OLAP многомерный способ представления данных исключительно на концептуальном уровне. Используемые им термины - "Многомерное концептуальное представление" ("Multidimensional conceptual view"), "Множественные измерения данных" ("Multiple data dimensions"), "Сервер OLAP" ("OLAP server") - не определяют физического механизма хранения данных (термины "многомерная база данных" и "многомерная СУБД" не встречаются ни разу).
Часто в публикациях аббревиатурой OLAP обозначается не только многомерный взгляд на данные, но и хранение самих данных в многомерной БД, что в принципе неверно.
По Кодду, многомерное концептуальное представление (multi-dimensional conceptual view) является наиболее естественным взглядом управляющего персонала на объект управления. Оно представляет собой множественную перспективу, состоящую из нескольких независимых измерений, вдоль которых могут быть проанализированы определенные совокупности данных. Одновременный анализ по нескольким измерениям данных определяется как многомерный анализ. Каждое измерение включает направления консолидации данных, состоящие из серии последовательных уровней обобщения, где каждый вышестоящий уровень соответствует большей степени агрегации данных по соответствующему измерению. Так, измерение Исполнитель может определяться направлением консолидации, состоящим из уровней обобщения "предприятие - подразделение - отдел - служащий". Измерение Время может даже включать два направления консолидации - "год - квартал - месяц - день" и "неделя - день", поскольку счет времени по месяцам и по неделям несовместим. В этом случае становится возможным произвольный выбор желаемого уровня детализаций информации по каждому
296
из измерений. Операция спуска (drilling down) соответствует движению от высших ступеней консолидации к низшим; напротив, операция подъема (rolling up) означает движение от низших уровней к высшим.
Следующим новым направлением в развитии систем управления базами данных является направление, связанное с отказом от нормализации отношений. Во многом нормализация отношений нарушает естественные иерархические связи между объектами, которые достаточно распространены в нашем мире. Возможность сохранять их на концептуальном (но не на физическом) уровне позволяет пользователям более естественно отражать семантику предметной области. В настоящий момент уже существует теоретическое обоснование работы с ненормализованными отношениями и практические реализации подобных систем.
Дальнейшим расширением в структурных преобразованиях являются объектно-ориентированные базы данных. В объектно- ориентированной парадигме предметная область моделируется как множество классов взаимодействующих объектов. Каждый объект характеризуется набором свойств, которые являются как бы его пассивными характеристиками и набором методов работы с этим объектом. Работать с объектом можно только с использованием его методов. Атрибуты объекта могут принимать определенное множество допустимых значений, набор конкретных значений атрибутов объекта определяет его состояние. Используя методы работы с объектом, можно изменять значение его атрибутов и тем самым как бы изменять состояние самого объекта. Множество объектов с одним и тем же набором атрибутов и методов образует класс объектов. Объект должен принадлежать только одному классу (если не учитывать возможности наследования). Допускается наличие примитивных предопределенных классов, объекты-экземпляры которых не имеют атрибутов: целые, строки и т. д. Класс, объекты которого могут служить значениями атрибута объектов другого класса, называется доменом этого атрибута.
Одной из наиболее перспективных черт объектно - ориентированной парадигмы является принцип наследования. Допускается порождение нового класса на основе уже существующего класса, и этот процесс называется наследованием. В этом случае новый класс, называемый подклассом существующего класса (суперкласса), наследует все атрибуты и методы суперкласса. В подклассе, кроме того, могут быть определены дополнительные атрибуты и методы. Различаются случаи простого и множественного наследования. В первом случае подкласс может определяться только на основе одного суперкласса, во втором случае суперклассов может быть несколько. Если в языке или системе поддерживается единичное наследование классов, набор классов образует древовидную иерархию. При поддержании множественного наследования классы связаны в ориентированный граф с корнем, называемый решеткой классов. Объект подкласса считается принадлежащим любому суперклассу этого класса.
Можно считать, что наиболее важным качеством ООБД (объектно - ориентированной базы данных), которое позволяет реализовать объектно - ориентированный подход, является учет поведенческого аспекта объектов.
В прикладных информационных системах, основывавшихся на БД с традиционной организацией (вплоть до тех, которые базировались на семантических моделях
297
данных), существовал принципиальный разрыв между структурной и поведенческой частями. Структурная часть системы поддерживалась всем аппаратом БД, ее можно было моделировать, верифицировать и т. д., а поведенческая часть создавалась изолированно. В частности, отсутствовали формальный аппарат и системная поддержка совместного моделирования и гарантий согласованности структурной (статической) и поведенческой (динамической) частей. В среде ООБД проектирование, разработка и сопровождение прикладной системы становятся процессом, в котором интегрируются структурный и поведенческий аспекты. Конечно, для этого нужны специальные языки, позволяющие определять объекты и создавать на их основе прикладную систему.
Специфика применения объектно-ориентированного подхода для организации и управления БД потребовала уточненного толкования классических концепций и некоторого их расширения.
Прежде всего, возникло направление, которое предполагает возможность хранения объектов внутри реляционной БД, тогда дополнительно необходимо предусмотреть хранение и использование специфических методов работы с этими объектами, а это в свою очередь требует расширения стандарта языка SQL. Частично это уже сделано в новом стандарте SQL3, однако там далеко не все вопросы получили однозначное разрешение.
Однако часть разработчиков придерживается мнения о необходимости полного отказа от реляционной парадигмы и перехода на объектно - ориентированную парадигму. Для перехода к объектно-ориентированным БД стандарт объектного проектирования был дополнен стандартизованными средствами доступа к базам данных (стандарт ODMG93).
Поставщики коммерческих СУБД немедленно отреагировали на эту потребность.
Практически каждая уважающая себя фирма обратилась к объектным технологиям и продуктивно сотрудничает с разработчиками объектно - ориентированных СУБД. IBM и Oracle доработали свои СУБД (соответственно, DB2 и ORACLE), добавив объектную надстройку над реляционным ядром системы. Другой путь выбрал Informix, который приобрел серьезную объектно-реляционную СУБД Illustra и встроил ее в свою СУБД. В результате получился продукт, именующийся универсальным сервером. Другой лидер рынка СУБД - Computer Associates, поступил иначе. Он сделал ставку на чисто объектную базу Jasmine, активно пропагандируя ее достоинства. Кто прав - покажет будущее.
Следующим направлением развития баз данных является появление так называемых темпоральных баз данных, то есть баз данных, чувствительных ко времени. Фактически БД моделирует состояние объектов предметной области в некоторый текущий момент времени. Однако в ряде прикладных областей необходимо исследовать именно изменение состояний объектов во времени. Если использовать чисто реляционную модель, то требуется строить и хранить дополнительно множество отношений, имеющих одинаковые схемы, отличающиеся временем существования или снятия данных. Гораздо перспективнее и удобнее для этого использовать специальные механизмы снятия срезов по времени для определенных объектов БД. Основной тезис темпоральных систем состоит в том, что для любого объекта данных, созданного в момент времени t1 и уничтоженного в момент времени t2, в БД сохраняются (и доступны пользователям) все его состояния
298
во временном интервале (t1, t2). При обозначении интервала квадратные скобки означают, что граница интервала включена в него, а круглые скобки означают, что точка на временной оси, соответствующая границе интервала, не включается в интервал. И действительно, если объект уничтожен в момент времени t2, то в этой точке временной оси он уже не существует, поэтому мы оставляем правую границу временного интервала открытой.
Еще одним из перспективных направлений развития баз данных является направление, связанное с объединением технологии экспертных систем и баз данных и развитие так называемых дедуктивных баз данных.
Эти базы основаны на выявлении новых знаний из баз данных не путем запросов или аналитической обработки, а путем использования правил вывода и построения цепочек применения этих правил для вывода ответов на запросы. Для этих баз данных существуют языки запросов, отличные от классического SQL. В экспертных системах также знания экспертов хранятся в форме правил, чаще всего используются так называемые продукционные правила типа "если описание ситуации, то описание действия". Хранение подобных правил и организация вывода на основании имеющихся фактов под силу современным СУБД.
И наконец, последним, но, может быть, самым значительным направлением развития баз данных является перспектива взаимодействия Web - технологии и баз данных. Простота и доступность Web - технологии, возможность свободной публикации информации в Интернете, так чтобы она была доступна любому количеству пользователей, несомненно, сразу завоевали авторитет у большого числа пользователей. Однако процесс накопления слабоструктурированной информации быстро проходит и далее наступает момент обеспечения эффективного управления этой разнообразной информацией. И это уже серьезная проблема. Некоторые исследователи даже вывели определенную тенденцию, которая выражается в том, что наиболее популярные сайты со временем становятся неуправляемыми, в море информации невозможно отыскать то, что требуется. С одной стороны, Web представляет собой одну громадную базу данных. Однако до сих пор, вместо того чтобы превратиться в неотъемлемую часть инфраструктуры Web, базы данных остаются на вторых ролях. Во-первых, дизайнеры крупнейших Web-серверов с миллионами страниц содержимого постепенно перекладывают задачи управления страницами с файловых систем на системы баз данных. Во-вторых, системы баз данных используются в качестве серверов электронной коммерции, помогая отслеживать профили, транзакции, счета и инвентарные листы. В-третьих, ведущие Web - издатели примериваются к использованию систем баз данных для хранения информационного наполнения, имеющего сложную природу.
Однако в подавляющей части Web - узлов, особенно в тех, которые принадлежат провайдерам и держателям поисковых машин, технология баз данных не применяется. В небольших Web-узлах, как правило, используются статические HTML - страницы, хранящиеся в обычных файловых системах.
В будущем статические HTML-страницы все чаще станут заменять системами управления динамически формируемым содержимым. Уже сейчас, например, торговцы по каталогам не просто преобразуют бумажные каталоги в наборы статических HTML - страниц. Фактически они представляют электронный каталог, позволяющий заказчикам оперативно узнать то, что их интересует, не пролистывая
299
ненужную информацию: например, продает ли поставщик серые джемперы большого размера. Продавцы предлагают клиентам персонализированные манекены, позволяющие увидеть, как будет сидеть на них одежда. Для персонализации требуются весьма сложные модели данных.
HTML расширяется до XML, языка расширяемой разметки, который лучше описывает структурированные данные. К сожалению, XML, похоже, способен породить хаос в системах баз данных. Развивающийся подъязык запросов XML напоминает процедурные языки обработки запросов, превалировавшие 25 лет тому назад. Кроме того, XML стимулирует использование кэшей (наборов) данных на стороне клиента с поддержкой обновлений, что заставляет разработчиков погружаться в трясину проблем распределенных транзакций. К несчастью, значительная часть работ по XML происходит без серьезного участия сообщества исследователей систем баз данных. Авторы Web - публикаций нуждаются в инструментах для быстрого и экономичного построения хранилищ данных, рассчитанных на сложные приложения. Это, в свою очередь, формирует требования к технологии баз данных для создания, управления, поиска и обеспечения безопасности содержимого Web-узлов.
С другой стороны, универсальность Web-клиента становится весьма привлекательной для разработчиков несложных приложений, которые смогут работать с базами данных. В этом случае не требуется установка каждого клиента, достаточно выслать код доступа и клиент автоматически может уже работать с базой данных, при этом вам все равно, где находится клиент, он может работать как в локальной, так и в глобальной сети, если технология это позволяет.
А это весьма удобно, если вы можете с любого рабочего места, имея соответствующий пароль, получить доступ к необходимым данным. Подобные системы называются системами, разработанными по интранет - технологии, то есть технологии, использующей принципы технологий Интернета, но реализованные во внутренней локальной сети.
Для разработки интернет - приложений, которые связаны с базами данных, широко используются новые средства программирования: это язык PERL, язык PHP (Personal Home Page Tools), язык Javascript и ряд других. Это действительно грандиозно и, главное, очень интересно, но это уже темы для других книг. Пробуйте и дерзайте, я думаю, познакомившись с базами данных, вы еще не раз с ними столкнетесь в жизни. Я желаю вам успехов и корректных запросов к базам данных. Вы ведь уже знаете: каков вопрос, таков и ответ. Любая база данных может стать вашим помощником или мучителем, это зависит от разработчиков, мне хочется, чтобы для вас они всегда играли только первую роль.
Журнал транзакций
Реализация в СУБД принципа сохранения промежуточных состояний, подтверждения или отката транзакции обеспечивается специальным механизмом, для поддержки которого создается некоторая системная структура, называемая Журналом транзакций.
Однако назначение журнала транзакций гораздо шире. Он предназначен для обеспечения надежного хранения данных в БД.
А это требование предполагает, в частности, возможность восстановления согласованного состояния базы данных после любого рода аппаратных и программных сбоев. Очевидно, что для выполнения восстановлений необходима некоторая дополнительная информация. В подавляющем большинстве современных реляционных СУБД такая избыточная дополнительная информация поддерживается
221
в виде журнала изменений базы данных, чаще всего называемого Журналом транзакций.
Итак, общей целью журнализации изменений баз данных является обеспечение возможности восстановления согласованного состояния базы данных после любого сбоя. Поскольку основой поддержания целостного состояния базы данных является механизм транзакций, журнализация и восстановление тесно связаны с понятием транзакции. Общими принципами восстановления являются следующие:
результаты зафиксированных транзакций должны быть сохранены в восстановленном состоянии базы данных;
результаты незафиксированных транзакций должны отсутствовать в восстановленном состоянии базы данных.
Это, собственно, и означает, что восстанавливается последнее по времени согласованное состояние базы данных.
Возможны следующие ситуации, при которых требуется производить восстановление состояния базы данных.
Индивидуальный откат транзакции. Этот откат должен быть применен в следующих случаях:
стандартной ситуацией отката транзакции является ее явное завершение оператором ROLLBACK;
аварийное завершение работы прикладной программы, которое логически эквивалентно выполнению оператора ROLLBACK, но физически имеет иной механизм выполнения;
принудительный откат транзакции в случае взаимной блокировки при параллельном выполнении транзакций.
В подобном случае для выхода из тупика данная транзакция может быть выбрана в качестве "жертвы" и принудительно прекращено ее выполнение ядром СУБД.
Восстановление после внезапной потери содержимого оперативной памяти (мягкий сбой). Такая ситуация может возникнуть в следующих случаях:
при аварийном выключении электрического питания;
при возникновении неустранимого сбоя процессора (например, срабатываний контроля оперативной памяти) и т. д. Ситуация характеризуется потерей той части базы данных, которая к моменту сбоя содержалась в буферах оперативной памяти.
Восстановление после поломки основного внешнего носителя базы данных (жесткий сбой). Эта ситуация при достаточно высокой надежности современных устройств внешней памяти может возникать сравнительно редко, но тем не менее СУБД должна быть в состоянии восстановить базу данных даже и в этом случае. Основой восстановления является архивная копия и журнал изменений базы данных.
Для восстановления согласованного состояния базы данных при индивидуальном откате транзакции нужно устранить последствия операторов модификации
222
базы данных, которые выполнялись в этой транзакции. Для восстановления непротиворечивого состояния БД при мягком сбое необходимо восстановить содержимое БД по содержимому журналов транзакций, хранящихся на дисках. Для восстановления согласованного состояния БД при жестком сбое надо восстановить содержимое БД по архивным копиям и журналам транзакций, которые хранятся на неповрежденных внешних носителях.
Во всех трех случаях основой восстановления является избыточное хранение данных. Эти избыточные данные хранятся в журнале, содержащем последовательность записей об изменении базы данных.
Возможны два основных варианта ведения журнальной информации. В первом варианте для каждой транзакции поддерживается отдельный локальный журнал изменений базы данных этой транзакцией. Такие журналы называются локальными журналами. Они используются для индивидуальных откатов транзакций и могут поддерживаться в оперативной (правильнее сказать, в виртуальной) памяти.
Кроме того, поддерживается общий журнал изменений базы данных, используемый для восстановления состояния базы данных после мягких и жестких сбоев.
Этот подход позволяет быстро выполнять индивидуальные откаты транзакций, но приводит к дублированию информации в локальных и общем журналах. Поэтому чаще используется второй вариант - поддержание только общего журнала изменений базы данных, который используется и при выполнении индивидуальных откатов Далее мы рассматриваем именно этот вариант.
Общая структура журнала условно может быть представлена в виде некоторого последовательного файла, в котором фиксируется каждое изменение БД, которое происходит в ходе выполнения транзакции. Все транзакции имеют свои внутренние номера, поэтому в едином журнале транзакций фиксируются все изменения, проводимые всеми транзакциями.
Каждая запись в журнале транзакций помечается номером транзакции, к которой она относится, и значениями атрибутов, которые она меняет. Кроме того, для каждой транзакции в журнале фиксируется команда начала и завершения транзакции (см рис. 11.3).
Для большей надежности журнал транзакций часто дублируется системными средствами коммерческих СУБД, именно поэтому объем внешней памяти во много раз превышает реальный объем данных, которые хранятся в хранилище.
Имеются два альтернативных варианта ведения журнала транзакций: протокол с отложенными обновлениями и протокол с немедленными обновлениями.
Ведение журнала по принципу отложенных изменений предполагает следующий механизм выполнения транзакций:
Когда транзакция Т1 начинается, в протокол заносится запись
На протяжении выполнения транзакции в протоколе для каждой изменяемой записи записывается новое значение: . Здесь ID_RECORD - уникальный номер записи.
223
Если все действия, из которых состоит транзакция Т1, успешно выполнены, то транзакция частично фиксируется и в протокол заносится
После того как транзакция фиксирована, записи протокола, относящиеся к Т1, используются для внесения соответствующих изменений в БД.
Если происходит сбой, то СУБД просматривает протокол и выясняет, какие транзакции необходимо переделать. Транзакцию Т1 необходимо переделать, если протокол содержит обе записи и . БД может находиться в несогласованном состоянии, однако все новые значения измененных элементов данных содержатся в протоколе, и это требует повторного выполнения транзакции. Для этого используется некоторая системная процедура REDO( ), которая заменяет все значения элементов данных на новые, просматривая протокол в прямом порядке.
Если в протоколе не содержится команда фиксации транзакции COMMIT, то никаких действий проводить не требуется, а транзакция запускается заново.
Рис. 11.3. Журнал транзакций
Альтернативный механизм с немедленным выполнением предусматривает внесение изменений сразу в БД, а в протокол заносятся не только новые, но и все старые значения изменяемых атрибутов, поэтому каждая запись выглядит . При этом запись в журнал предшествует непосредственному выполнению операции над БД. Когда транзакция фиксируется, то есть встречается команда и она выполняется, то все изменения оказываются уже внесенными в БД и не требуется никаких дальнейших действий по отношению к этой транзакции.
224
При откате транзакции выполняется системная процедура UNDO(), которая возвращает все старые значения в отмененной транзакции, последовательно проходя по протоколу начиная с команды BEGIN TRANSACTION.
Для восстановления при сбое используется следующий механизм:
Если транзакция содержит команду начала транзакции, но не содержит команды фиксации с подтверждением ее выполнения, то выполняется последовательность действий как при откате транзакции, то есть восстанавливаются старые значения.
Если сбой произошел после выполнения последней команды изменения БД, но до выполнения команды фиксации, то команда фиксации выполняется, а с БД никаких изменений не происходит. Работа происходит только на уровне протокола.
Однако следует отметить, что проблемы восстановления выглядят гораздо сложнее приведенных ранее алгоритмов, с учетом того, что изменения как в журнал, так и в БД заносятся не сразу, а буферируются.Этому посвящен следующий раздел.
Журнализация и буферизация
Журнализация изменений тесно связана не только с управлением транзакциями, но и с буферизацией страниц базы данных в оперативной памяти.
Если бы запись об изменении базы данных, которая должна поступить в журнал при выполнении любой операции модификации базы данных, реально немедленно записывалась бы во внешнюю память, это привело бы к существенному замедлению работы системы. Поэтому записи в журнале тоже буферизуются: при нормальной работе очередная страница выталкивается во внешнюю память журнала только при полном заполнении записями.
Проблема состоит в выработке некоторой общей политики выталкивания, которая обеспечивала бы возможность восстановления состояния базы данных после сбоев.
Проблема не возникает при индивидуальных откатах транзакций, поскольку в этих случаях содержимое оперативной памяти не утрачено и можно пользоваться содержимым как буфера журнала, так и буферов страниц базы данных. Но если произошел мягкий сбой и содержимое буферов утрачено, для проведения восстановления базы данных необходимо иметь некоторое согласованное состояние журнала и базы данных во внешней памяти.
Основным принципом согласованной политики выталкивания буфера журнала и буферов страниц базы данных является то, что запись об изменении объекта базы данных должна попадать во внешнюю память журнала раньше, чем измененный объект оказывается во внешней памяти базы данных. Соответствующий протокол журнализации (и управления буферизацией) называется Write Ahead Log (WAL) - "пиши сначала в журнал" и состоит в том, что если требуется записать во внешнюю память измененный объект базы данных, то перед этим нужно гарантировать запись во внешнюю память журнала транзакций записи о его изменении.
225
Другими словами, если во внешней памяти базы данных находится некоторый объект базы данных, по отношению к которому выполнена операция модификации, то во внешней памяти журнала обязательно находится запись, соответствующая этой операции. Обратное неверно, то есть если во внешней памяти журнале содержится запись о некоторой операции изменения объекта базы данных, то сам измененный объект может отсутствовать во внешней памяти базы данных.
Дополнительное условие на выталкивание буферов накладывается тем требованием, что каждая успешно завершившаяся транзакция должна быть реально зафиксирована во внешней памяти. Какой бы сбой не произошел, система должна быть в состоянии восстановить состояние базы данных, содержащее результаты всех зафиксированных к моменту сбоя транзакций.
Простым решением было бы выталкивание буфера журнала, за которым следует массовое выталкивание буферов страниц базы данных, изменявшихся данной транзакцией. Довольно часто так и делают, но это вызывает существенные накладные расходы при выполнении операции фиксации транзакции.
Оказывается, что минимальным требованием, гарантирующим возможность восстановления последнего согласованного состояния базы данных, является выталкивание при фиксации транзакции во внешнюю память журнала всех записей об изменении базы данных этой транзакцией. При этом последней записью в журнал, производимой от имени данной транзакции, является специальная запись о конце транзакции.
Рассмотрим теперь, как можно выполнять операции восстановления базы данных в различных ситуациях, если в системе поддерживается общий для всех транзакций журнал с общей буферизацией записей, поддерживаемый в соответствии с протоколом WAL.