Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil
Шрифт:
Все. что хранится на различных страницах базы данных, необходимо как-то организовать в памяти компьютера, преобразовать данные из файла базы данных в совокупность внутрисерверных объектов и переменных. Эта совокупность называется внутренним образом базы данных (internal database image), по терминологии Анн Харрисон.
Итак, попробуем рассмотреть процесс построения внутреннего образа базы данных.
* Сервер читает 1024 байта из начала файла и, если это действительно файл базы данных InterBase, определяет размер страницы этой базы и перечитывает всю заголовочную страницу целиком.
* С заголовочной страницы сервер извлекает номер страницы указателей, на которой хранятся ссылки на страницы данных, определяющие таблицу RDB$Pages.
* Сервер переходит к этой
* Получив данные о распределении страниц по отношениям (relations, в сущности, это то же самое, что и обычные таблицы, и для упрощения можно мысленно подменять эти понятия), InterBase начинает формировать структуры данных: сначала системные таблицы, ограничения и индексы, а потом уже пользовательские объекты.
* После инициализации системных и пользовательских метаданных (так называют таблицы, ограничения, индексы и все остальные объекты базы данных), InterBase возвращает пользователю, попросившему открыть базу данных, handle этой базы данных (некоторые используют термин "рукоятка" или просто транскрипцию английского слова - "хэндл"). В сущности, handle - это некоторый идентификатор, который указывает InterBase, с какой именно базой данных работать, поскольку одновременно могут работать несколько пользователей, а значит, могут быть открыты несколько баз данных.
* После этих операций база данных считается открытой и сервер готов выполнять запросы пользователей к ней.
Теперь, когда проложен некоторый "мост", связывающий физическую и логическую структуру базы данных, можно переходить к особенностям логической структуры.
Логическая структура базы данных InterBase
Логическая структура - понятие достаточно расплывчатое, поэтому мы попробуем постепенно освоить ключевые идеи, надеясь, что позже они создадут интуитивно понятное ощущение. Первое, что мы рассмотрим из относящегося к логической структуре базы данных, это системные таблицы и их содержимое.
Системные таблицы описывают метаданные, как системные, так и пользовательские. Вообще говоря, термин "метаданные" означает "данные, описывающие множество данных". Приставка "мета-" означает "описывает множество". Например, метаязык - это язык, описывающий множество языков. Метаданные описывают пользовательские данные, т. е. таблицы, триггеры, представления, хранимые процедуры и т. д.
– все, что реализует правила хранения и обработки той информации, ради хранения и обработки которой и создается конкретная база данных.
Довольно забавно в первый раз узнать, что все метаданные, - как пользовательские таблицы, триггеры, представления, так и все системные объекты, - хранятся в таких же точно таблицах, из которых можно читать и писать данные с помощью обычных SQL-запросов. Эти таблицы "визуально" отличаются только тем, что их имена начинаются с RDB$. Эти 4 символа зарезервированы для имен системных объектов, ни одна пользовательская таблица, столбец или другой объект не имеют права обладать именами, начинающимися с этих символов. Формально ничто не мешает создать вам таблицу, название которой начинается с зарезервированных символов, однако документация InterBase настойчиво не рекомендует этого делать.
Возникает вопрос: если данные о структуре таблиц базы данных хранятся в точно таких же таблицах, как и пользовательские, то где хранится информация о самих этих таблицах, которые описывают таблицы? Классический пример проблемы "курицы и яйца" - как одно могло появиться раньше другого, если они взаимозависимы? Решение состоит в том, что системные таблицы в их первозданном состоянии "прошиты" в исходных кодах InterBase и автоматически разворачиваются
при создании базы данных в определенном порядке.Мы уже говорили о таблице RDB$Pages, которая ставит в соответствие физические страницы в файлах базы данных определенным объектам этой базы данных. Структура этой таблицы приведена в табл. 4.24:
Табл 4.24. Системная таблица RDB$Pages
Column name (имя поля) | Datatype (тип данных) | Description (описание) |
RDB$PAGE_NUMBER | INTEGER | Номер физической страницы |
RDB$RELATION_ID | SMALLINT | Идентификатор таблицы, для которой распределена страница |
RDB$PAGE_SEQUENCE | INTEGER | Порядковый номер этой страницы |
RDB$PAGE_TYPE | SMALLINT | Тип страницы - см. таблицу 4.22 |
Каждая страница данных в базе данных поставлена в соответствие какой- либо таблице, т. е. RELATION. Эту связь поддерживает поле RDB$RE- LATION_ID, в котором хранится ссылка на таблицу. Как было описано выше, в процессе построения внутреннего образа базы, сервер по определенному жестко "зашитому" в него алгоритму строит эту таблицу и наполняет ее данными. Если быть точным, то в момент построения образа базы данных RDB$Pages является не таблицей, а просто массивом данных определенного формата, известного InterBase. На основании определенного алгоритма сервер считывает данные из этого массива и строит следующую критическую для всей базы таблицу - RDB$Relations. Эта таблица описывает все таблицы базы. Если мы сделаем SQL-запрос: SELECT " from RDB$Relations с целью выяснить, ссылки на какие таблицы содержит RDBSRELATIONS, гочви шм. что она содержит и RDBSPages, и саму себя. Очевидно, что в данном случае сервер слегка "хитрит", "задним числом" подставляя эти и остальные системные таблицы в RDB$Relations, таким образом, "легализуя" их. Сервер регистрирует их как "нормальные" таблицы, в которые можно добавить записи или удалить, т. е. предоставляет стандартный SQL-интерфейс для работы с метаданными.
Может возникнуть вполне резонный вопрос: зачем бы разработчикам InterBase "подстраивать" свои системные данные под пользовательский интерфейс? Ведь внутренние механизмы доступа и чтения были бы быстрее. Разумеется, есть большой резон в том, чтобы предоставить универсальный механизм работы с таблицами, описывающими метаданные.
Дело в том. что логическая структура базы данных состоит не только из таблиц, но и из других объектов. В InterBase существуют следующие объекты:
* Table (таблица);
* View (представление);
* Trigger (триггер);
* Computed_field (вычисляемое поле);
* Validation (проверка);
* Procedure (процедура);
* Epression_index (вычисляемый индекс);
* Exception (исключение);
* User (польюватель),
* Field (поле);
* Index (индекс);
* Usei-Defined Function (UDF) - функция, определяемая пользователем.
Пока, может быть, не совсем очевидно назначение некоторых из этих объектов, но ясно, что их необходимо описывать и хранить в некотором виде, удобном как для пользователя, так и для доступа из ядра InterBase. Лучше всего это сделать, сохранив все эти объекты в системных таблицах. Их добавление и модификация производятся с помощью SQL-запросов. Не правда ли, элегантное решение9 Реализация сервера полностью отделена от конкретной базы данных — все взаимосвязи описываются SQL и его расширениями - языком хранимых процедур и триггеров.