2008 г.
Базы данных. Вводный курс
Сергей Кузнецов
Назад Содержание Вперёд
12.2.4. Интерфейс RSS
Следует
заметить, что описываемый в этом подразделе интерфейс RSS не
соответствует в точности ни одной из публикаций, посвященных System
R,
а является скорее некоторой компиляцией, согласующейся с
завершающими публикациями.
На
уровне RSS отсутствует именование объектов базы данных,
употребляемое на уровне SQL. Вместо имен объектов используются их
уникальные идентификаторы, являющиеся прямыми или косвенными
адресами внутренних описателей объектов
во внешней
памяти для постоянных объектов или в основной памяти для временных
объектов. Замена имен объектов базы данных на их идентификаторы
производится компилятором SQL
на основе информации, черпаемой им из системных таблиц-каталогов.
Можно выделить
следующие группы операций:
- операции
сканирования таблиц и списков;
- операции
создания и уничтожения постоянных и временных объектов базы данных;
- операции
модификации таблиц и списков;
- операция
добавления поля к таблице;
- операции
управления прохождением транзакций;
- операция
явной синхронизации.
Операции сканирования таблиц и списков
Операции
группы сканирования позволяют последовательно, в порядке,
определяемом типом сканирования, прочитать кортежи таблицы или
списка, удовлетворяющие требуемым условиям. Группа включает операции
OPEN
,
NEXT
и CLOSE
,
означающие, соответственно, начало сканирования, требование чтения
следующего кортежа, удовлетворяющего условиям, и конец сканирования.
Для
таблицы возможны два режима сканирования: прямое сканирование и
сканирование через индекс. При прямом сканировании единственным
параметром операции OPEN
является идентификатор таблицы (включающий и идентификатор сегмента,
в котором эта таблица хранится). По причине того, что в System R
допускается размещение в одной странице данных кортежей нескольких
таблиц, прямое сканирование предполагает последовательный просмотр
всех страниц сегмента с выделением в них кортежей, входящих в данную
таблицу; это очень дорогой способ сканирования таблицы. При этом
порядок выборки кортежей определяется их физическим размещением в
страницах сегмента, т.е. предопределен системой.
При
начале сканирования таблицы через индекс в число параметров операции
OPEN
входит идентификатор какого-либо индекса, определенного ранее на
полях этой таблицы. Кроме того, можно указать диапазон сканирования
в терминах значений поля (полей), составляющего ключ индекса. При
открытии сканирования через индекс производится начальная установка
указателя сканирования в позицию листа B-дерева (см. подраздел 12.3.2. Индексы)
индекса, соответствующую левой границе заданного диапазона. Процесс
сканирования состоит в последовательном продвижении по листовым
вершинам индекса до достижения правой границы диапазона сканирования
с выборкой идентификаторов кортежей и чтением соответствующих
кортежей. Легко видеть, что в худшем случае может потребоваться
столько чтений страниц данных из внешней памяти, сколько
идентификаторов кортежей было встречено, т.е. эффективность
сканирования по индексу определяется «широтой» заданного
диапазона сканирования. При этом, конечно, имеется то преимущество,
что порядок сканирования соответствует порядку возрастания или
убывания значений ключа индекса.
Наконец,
при сканировании списка, как и при прямом сканировании таблицы,
единственным параметром операции OPEN
является идентификатор списка, но, в отличие от прямого сканирования
таблицы это сканирование максимально эффективно: читаются только
страницы, содержащие кортежи из данного списка, и порядок
сканирования совпадает с порядком занесения кортежей в список или
порядком списка, если он упорядочен.
В результате
успешного выполнения операции открытия сканирования (если нет ошибок
в параметрах) вырабатывается и возвращается идентификатор
сканирования, который используется в качестве аргумента других
операций этой группы.
Операция
NEXT
выполняет чтение следующего кортежа указанного сканирования,
удовлетворяющего условию данной операции. Условие представляет собой
дизъюнктивную нормальную форму простых условий, накладываемых на
значения указанных полей таблицы. Простое условие – это
условие вида номер-поля
op константа
,
где op
– операция сравнения <
,
<=
,
>
,
>=
,
=
или !=
.
Общее условие является параметром операции NEXT
.
Семантика
операции NEXT
следующая: начиная с текущей позиции сканирования выбираются кортежи
таблицы в порядке, определяемом типом сканирования, до тех пор, пока
не встретится кортеж, значения полей которого удовлетворяют
указанному условию. Этот кортеж и является результатом операции.
Если при выборке кортежа достигается правая граница диапазона
сканирования (правая граница значения ключа при сканировании через
индекс или последний кортеж таблицы или списка при прямом
сканировании), то вырабатывается особый признак результата. После
этого единственным разумным действием является закрытие сканирования
– операция CLOSE
Операция
CLOSE
может быть выполнена в данной транзакции по отношению к любому ранее
открытому сканированию независимо от его состояния (т.е. независимо
от того, достигнута ли при сканировании правая граница диапазона
сканирования). Параметром операции является идентификатор
сканирования, и ее выполнение приводит к тому, что этот
идентификатор становится недействительным (и, соответственно,
уничтожаются служебные структуры памяти RSS, относящиеся к данному
сканированию).
Операции создания и уничтожения постоянных и временных объектов базы данных
Группа
операций создания и уничтожения постоянных и временных объектов базы
данных включает операции создания таблиц (CREATE
TABLE
),
списков (CREATE LIST
),
индексов (CREATE
IMAGE
) и
уничтожения любого из подобных объектов (DROP
TABLE
, DROP
LIST
и DROP
IMAGE
).
Входным параметром операций создания таблиц и списков является
спецификатор структуры объекта, т.е. число полей объекта и
спецификаторы их типов. Кроме того, при спецификации полей таблицы
указывается разрешение или запрещение наличия неопределенных
значений полей в кортежах этой таблицы или списка. Неопределенные
значения кодируются специальным образом. Любая операция сравнения
константы данного типа с неопределенным значением по определению
вырабатывает значение false,
кроме операции сравнения на совпадение со специальной литеральной
константой NULL.
В
результате выполнения этих операций заводится описатель в служебной
таблице описателей таблиц или основной памяти (в зависимости от
того, создается ли постоянный объект или временный), и
вырабатывается идентификатор объекта, который служит входным
параметром других операций, относящихся к соответствующему объекту
(в частности, параметром операции OPEN
при открытии сканирования объекта).
Входными
параметрами операции CREATE
IMAGE
являются идентификатор таблицы, для которой создается индекс, список
номеров полей, значения которых составляют ключ индекса, и признаки
упорядочения по возрастанию или убыванию для всех полей,
составляющих ключ. Кроме того, может быть указан признак
уникальности индекса, т.е. запрещения наличия в данном индексе
ключей-дубликатов. Если операция выполняется по отношению к пустой в
этот момент таблице, то выполнение операции такое же простое, как и
для операций создания таблиц и списков: создается описатель в
служебной таблице описателей индексов и возвращается идентификатор
индекса (который, в частности, используется в качестве аргумента
операции открытия сканирования таблицы через индекс).
Если же к моменту
создания индекса соответствующая таблица не пуста (а это
допускается), то операция становится существенно более
дорогостоящей, поскольку при ее выполнении происходит реальное
создание B-дерева индекса, что требует, по меньшей мере, одного
последовательного просмотра таблицы. При этом, если создаваемый
индекс имеет признак уникальности, то это контролируется при
создании B-дерева, и если уникальность нарушается, то операция не
выполняется (т.е. индекс не создается). Из этого следует, что хотя
создание индексов в динамике не запрещается, более эффективно
создавать все индексы на данной таблице до ее заполнения. Заметим,
что создание кластеризованного индекса для непустой таблицы
запрещено, поскольку соответствующую кластеризацию таблицы без ее
реструктуризации получить невозможно.
Операции
DROP TABLE
,
DROP LIST
и DROP IMAGE
могут быть выполнены в любой момент независимо от состояния
объектов. Выполнение операции приводит к уничтожению
соответствующего объекта и, вследствие этого, недействительности его
идентификатора.
Следует
отметить, что массовые операции над постоянными объектами (CREATE
IMAGE
и DROP
TABLE
)
требуют дополнительных накладных расходов в связи с необходимостью
обеспечения возможности откатов транзакции, для чего требуется
выполнение массовых обратных действий. Особенно сильно это
затрагивает операцию уничтожения непустых таблиц, поскольку требует
журнализации всех кортежей, содержащихся в них к моменту
уничтожения. Поэтому, хотя уничтожение непустых таблиц и не
запрещено, нужно иметь в виду, что это очень дорогостоящая операция.
Операции модификации таблиц и списков
Группа
операций модификации таблиц и списков включает операции вставки
кортежа в таблицу или список (INSERT
),
удаления кортежа из таблицы (DELETE
)
и обновления кортежа в таблице (UPDATE
).
Параметрами
операции вставки кортежа являются идентификатор таблицы или списка и
набор значений полей кортежа. Среди значений полей могут быть
литеральные неопределенные значения NULL. Естественно, при
выполнении операции контролируется допустимость неопределенных
значений в соответствующих полях. При занесении кортежа в
кластеризованную таблицу поиск места в сегменте под кортеж
производится с использованием кластеризованного индекса: система
пытается вставить кортеж в страницу данных, уже содержащую кортежи с
теми же или близкими значениями полей кластеризации. При занесении
кортежа в некластеризованную таблицу место под кортеж выделяется в
первой подходящей странице данных. Наконец, при вставке кортежа в
список он помещается в конец списка.
При
занесении кортежа в таблицу производится коррекция всех индексов,
определенных на этой таблице. Реально это выражается во вставке
новой записи во все B-деревья индексов. При этом могут произойти
переполнения одной или нескольких страниц индекса, что вызовет
переливание части записей в соседние страницы или расщепление
страниц. Если индекс определен с атрибутом уникальности, то
проверяется соблюдение этого условия,
и если оно
нарушено, операция вставки считается невыполненной. Из этого видно,
что операция вставки кортежа тем более накладна, чем больше индексов
определено для данной таблицы (это относится и к операциям удаления
и модификации кортежей).
В результате
успешного выполнения операции вставки кортежа в таблицу
вырабатывается идентификатор нового кортежа, который выдается в
качестве результата операции и может быть в дальнейшем использован
как прямой параметр операций удаления и модификации кортежей
таблицы. При занесении кортежа в список значение идентификатора
кортежа не вырабатывается (для списков допускается только
последовательное сканирование и добавление новых кортежей в конец
списка; над ними нельзя определить индексов, и поэтому косвенная
адресация кортежей списков через их идентификаторы не требуется).
Операции
удаления и модификации кортежей допускаются только для кортежей
таблиц. Естественно, что для выполнения этих операций необходимо
идентифицировать соответствующий кортеж. В интерфейсе RSS
допускаются два способа такой идентификации: с помощью
идентификатора кортежа (явная адресация) и с использованием
идентификатора открытого к этому времени сканирования. Первый
вариант возможен, поскольку идентификатор кортежа сообщается как
ответный параметр операции занесения кортежа в постоянную таблицу.
При идентификации кортежа с помощью идентификатора сканирования
имеется в виду кортеж, прочитанный с помощью последней операции
NEXT
.
Если при такой идентификации выполняется операция DELETE
или операция UPDATE
,
задевающая порядок сканирования (т.е. сканирование ведется по
индексу и операция модификации меняет поле кортежа, входящее в
состав ключа этого индекса), то текущий кортеж сканирования
теряется, и его идентификатор нельзя использовать для идентификации
кортежа, пока не будет выполнена следующая операция NEXT
.
Единственным
параметром операции DELETE
является идентификатор кортежа или идентификатор сканирования.
Параметры операции UPDATE
включают, кроме этого, спецификацию изменяемых полей кортежа (список
номеров полей и их новых значений). Среди значений могут находиться
литеральные изображения неопределенных значений, если
соответствующие поля таблицы допускают хранение неопределенных
значений. При выполнении операции DELETE
производится коррекция всех индексов, определенных на данной
таблице. Операция UPDATE
также может повлечь коррекцию индексов, если затрагивает поля,
входящие в состав их ключей.
Кроме
описанных «атомарных» операций сканирования и
модификации таблиц и списков, интерфейс RSS включает одну
«макрооперацию» BUILDLIST
,
позволяющую за одно обращение к RSS построить список,
отсортированный в соответствии со значениями заданных полей. Эта
операция включает сканирование заданной таблицы или списка, создание
нового списка, в который включаются указанные поля выбираемых
кортежей, и сортировку построенного списка в соответствии со
значениями указанных полей. Идентификатор заново построенного
отсортированного списка является ответным параметром операции.
Соответственно,
параметрами операции BUILDLIST
являются набор параметров для открытия сканирования (допускается
любой способ сканирования), список номеров полей, составляющих
кортежи нового списка, и список номеров полей, по которым нужно
производить сортировку (как и в случае создания нового индекса,
можно отдельно для каждого из этих полей указать требование к
сортировке по возрастанию или убыванию значений данного поля).
Отдельным параметром операции BUILDLIST
является признак, в соответствии со значением которого в новом
списке допускаются или не допускаются кортежи-дубликаты.
Операция добавления поля к существующей таблице
Операция
RSS добавления поля к существующей таблице позволяет в динамике
изменять схему таблицы. Параметрами операции CHANGE
являются идентификатор существующей таблицы и спецификация нового
поля (его тип). При выполнении операции изменяется только описатель
данной таблицы в служебной таблице описателей таблиц. До выполнения
первой операции UPDATE
,
затрагивающей новое поле таблицы, реально ни в одном кортеже таблицы
память под новое поле выделяться не будет. По умолчанию значения
нового поля во всех кортежах таблицы, в которые еще не производилось
явное занесение значения, считаются неопределенными. Тем самым, ни
для одного поля, динамически добавленного к существующей таблице, не
может быть запрещено хранение неопределенных значений.
Операции управления прохождением транзакций
Каждая
операция RSS выполняется в пределах некоторой транзакции. Интерфейс
RSS включает набор операций управления прохождением транзакции:
начать транзакцию (BEGIN
TRANSACTION
),
закончить транзакцию (END
TRANSACTIO
N),
установить точку сохранения (SAVE
)
и выполнить откат до указанной точки сохранения или до начала
транзакции (RESTORE
).
Это
не отмечалось раньше, но на самом деле при вызове любой операции
функции RSS, кроме BEGIN
TRANSACTION
,
должен указываться еще один параметр – идентификатор
транзакции. Этот идентификатор и вырабатывается при выполнении
операции BEGIN
TRANSACTION
,
которая сама входных параметров не требует.
В
любой точке транзакции до выполнения операции END
TRANSACTION
может быть выполнен откат данной транзакции, т.е. обратное
выполнение всех изменений, произведенных в данной транзакции, и
восстановление состояния позиций сканирования. Откат может быть
произведен до начала транзакции (в этом случае о восстановлении
позиций сканирования говорить бессмысленно) или до установленной
ранее в транзакции точки сохранения.
Точка
сохранения устанавливается с помощью операции SAVE
.
При выполнении этой операции запоминаются состояние сканов данной
транзакции, открытых к моменту выполнения SAVE
,
и координаты последней записи об изменениях в базе данных в журнале,
произведенной от имени данной транзакции. Ответным параметром
операции SAVE
(а прямых параметров, кроме идентификатора транзакции, она не
требует) является идентификатор точки сохранения. Этот идентификатор
в дальнейшем может быть использован как аргумент операции RESTORE
,
при выполнении которой производится восстановление базы данных по
журналу (с использованием записей о ее изменениях от данной
транзакции) до того состояния, в котором находилась база данных к
моменту установки указанной точки сохранения. Кроме того, по
локальной информации в оперативной памяти, привязанной к транзакции,
восстанавливается состояние ее сканов. Откат к началу транзакции
инициируется также вызовом операции RESTORE
,
но с указанием некоторого предопределенного идентификатора точки
сохранения.
При
выполнении своих транзакций пользователи System R изолированы один
от другого, т.е. не ощущают того, что система функционирует в
многопользовательском режиме. Это достигается за счет наличия в RSS
механизма неявной синхронизации. До конца транзакции никакие
изменения базы данных, произведенные в пределах этой транзакции, не
могут быть использованы в других транзакциях (попытка использования
таких данных приводит к временным
синхронизационным блокировкам этих транзакций). При выполнении
операции END
TRANSACTION
происходит "фиксация" изменений, произведенных в данной
транзакции, т.е. они становятся видимыми в других транзакциях.
Реально это означает снятие синхронизационных блокировок с объектов
базы данных, изменявшихся в транзакции. Из этого следует, что после
выполнения END
TRANSACTION
невозможны индивидуальные откаты данной транзакции. RSS просто
делает недействительным идентификатор данной транзакции, и после
выполнения операции окончания транзакции отвергает все операции с
таким идентификатором.
Операция явной синхронизации
Последняя
операция интерфейса RSS – операция явной синхронизации LOCK
.
Эта операция позволяет установить явную синхронизационную блокировку
указанной таблицы (параметром операции является идентификатор
таблицы). Выполнение операции LOCK
гарантирует, что никакая другая транзакция до конца данной не сможет
изменить эту таблицу (вставить в нее новый кортеж, удалить или
модифицировать существующий), если установлена блокировка в режиме
чтения, или даже прочитать любой кортеж этой таблицы, если
установлена монопольная блокировка.
Из
всего, что говорилось раньше по поводу подхода к синхронизации в
System R и соответствующего разбиения системы на уровни, следует
нелогичность наличия этой операции в интерфейсе RSS. На самом деле,
логически эта операция избыточна, т.е. если бы ее не было, можно
было бы реализовать SQL с использованием оставшейся части операций.
Предварительно (до подробного обсуждения средств управления
транзакциями в лекции
13)
заметим, что операция LOCK
введена в интерфейс RSS для возможности оптимизации выполнения
запросов.
Дело
в том, что, как видно из описания интерфейса RSS, этот интерфейс
является покортежным. Следовательно, и информация для синхронизации
носит достаточно узкий характер. В то же время, на уровне SQL
имеется более полная информация. Например, если обрабатывается
предложение SQL DELETE
FROM table_name
,
то известно, что будут удалены все кортежи указанной таблицы.
Понятно, что как бы не реализовывался механизм синхронизации в RSS,
в данном случае выгоднее сообщить сразу, что изменения касаются всей
таблицы.
Но ситуации, в
которых очевидна выгода от использования явной синхронизации,
достаточно редки. Пользоваться этим средством можно только очень
осмотрительно, потому что неоправданные захваты таких крупных
объектов могут резко ограничить степень асинхронности выполнения
транзакций.
Назад Содержание Вперёд