Ова страница је машински преведена. Прочитајте енглески оригинал. English

IBSurgeon библиотека

Физичка структура базе података (InterBase и Firebird)

Алексей Ковязин, Сергей Востриков, последнее обновление 05-июня-2004

Физическая структура базы данных

Зачем нам изучать физическую структуру базы данных InterBase?

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

Итак, для чего предназначена система управления базами данных (СУБД)? Очевидно, для хранения и управления данными. Это звучит банально, но над этим стоит задуматься. Пользователь помещает данные в СУБД, которая некоторым образом преобразует эти данные в понятные ей внутренние форматы. Вы можете представить «0 и 1», если слова «внутренний формат данных» вызывают некоторые трудности с ассоциациями. СУБД хранит эти данные и по первому требованию должна извлечь их из своего формата, преобразовать в подходящий вид и передать пользователю.

Предмет этой главы - как СУБД хранит свои данные, в каком виде и как они организованы на самом низком уровне. Мы постараемся объяснить вам, как из битов и байтов, лежащих на жестком диске, мы получаем ценные данные.

Файлы базы данных InterBase

Обычно, когда мы говорим о базе данных, мы имеем в виду саму СУБД и пользовательскую информацию, а также клиентские программы, работающие с данными. В этой главе мы будем рассматривать базу данных как файлы базы данных.

База данных InterBase представляет собой один или несколько файлов, содержащих информацию обо всем, что связано с этой базой. Информация о пользователях является исключением, поскольку пользователи определяются на уровне всего сервера и хранятся отдельно, в базе данных безопасности admin.ib (в версиях до 7 это был ISC4.GDB).

Совет: обратитесь к главе «Безопасность сервера и базы данных», чтобы узнать больше о принципах безопасности InterBase.

Итак, вся информация о базе данных хранится в этих файлах: сами данные, индексы, триггеры, хранимые процедуры и т.д.

База данных InterBase для среднего проекта представляет собой один файл, поскольку современные версии InterBase могут использовать 64-битный ввод-вывод для работы с файлом данных, что дает возможность иметь файл данных размером до 64 ГБ. Более ранние версии InterBase имели ограничение в 4 гигабайта на каждый файл базы данных (до 64 Тбайт для всей базы данных). Как можно предположить, 64 гигабайт вполне достаточно для хранения информации практически любого приложения базы данных. Но при необходимости мы можем разделить базу данных на несколько файлов. Кстати, существуют базы данных InterBase размером в сотни гигабайт.

IBSurgeon - путеводитель по базе данных InterBase

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

Но, к счастью, существует инструмент для прямой работы с базами данных InterBase. Это IBSurgeon Editor - инструмент для прямой низкоуровневой работы с базами данных InterBase, который можно использовать для изучения внутренней структуры баз данных InterBase и диагностики поврежденных баз данных с целью их восстановления. Более подробно см. приложение «Инструменты администратора и разработчика InterBase».

IBSurgeon использует собственный альтернативный механизм доступа к базе данных, который позволяет открывать и просматривать базы данных в любом состоянии, включая сильно поврежденные, которые не могут быть открыты ядром сервера InterBase/FireBird/Yaffil.

Мы будем использовать IBSurgeon для иллюстрации внутренней структуры базы данных.

Файлы *.IB/*.FDB изнутри

IB - это расширение, рекомендуемое для файлов базы данных InterBase, а FDB - для Firebird (ранее это был GDB). Первое, что мы должны сказать о структуре файла IB, это то, что он представляет собой набор страниц строго определенного размера. Размер файла базы данных делится на размер страницы, который неизменен для всех файлов этой базы данных. Различные версии InterBase поддерживают разные размеры страниц, что показано в таблице 1. Размер страницы устанавливается при создании базы данных и не может быть изменен в течение ее жизненного цикла. Другими словами, мы можем изменить размер страницы только при восстановлении базы данных из резервной копии.

Таблица 1. Размеры страниц, поддерживаемые различными версиями InterBase

Версия InterBase Размер страницы, байт
1024 2048 4096 8192 16384
InterBase 4.0 * * * *
InterBase 5.x * * * *
InterBase 6.x-7.x * * * *

Чтение и запись данных в базе данных выполняются постранично, многие важные характеристики сервера и базы данных, такие как размер кэша базы данных, зависят от размера страницы и измеряются в «страницах».

Давайте откроем любую базу данных InterBase с помощью IBSurgeon. Достаточно дважды щелкнуть по файлу базы данных. Рисунок 1 показывает список страниц, который появляется после того, как IBSurgeon открыл базу данных:

![](/images/IB DB structure/InterBase database structure_html_m4f802417.png)

Рисунок 1. Список страниц базы данных

Страницы могут быть разных типов, каждый из которых служит определенной цели. Взаимосвязи различных типов условно представлены на рисунке 2. Рисунок 2 схематически изображает распределение страниц в файле базы данных - слева направо, сверху вниз, если считать от начала файла. Страницы одного типа не идут строго одна за другой - они могут быть легко перемешаны, распределены в файле в том порядке, в котором они были созданы сервером при расширении или создании баз данных.

![](/images/IB DB structure/InterBase database structure_html_4005a6b0.png)

Рисунок 2. Взаимосвязи между различными типами страниц в базе данных InterBase

Вы, должно быть, заметили, что некоторые типы страниц не имеют ссылок на другие типы страниц. Однако здесь нет противоречия, дело в том, что эти типы страниц связаны и используются на другом структурном уровне. Они могут быть связаны с таблицей RDB$PAGES и другими системными таблицами (эту таблицу и другие системные объекты мы рассмотрим ниже - в главе «Логическая структура базы данных»). На рисунке 2 мы можем видеть только явные ссылки между страницами на физическом уровне.

Рассмотрим подробно, какие типы страниц существуют в базе данных InterBase. В файле ods.h из набора исходных кодов InterBase содержится информация обо всех возможных типах страниц. Мы будем часто обращаться к этому файлу, чтобы получать данные не только об ODS, но и о многих других фундаментальных вещах ядра InterBase из первоисточника. Всего объявлено 11 типов страниц, но только 9 из них заслуживают объяснения (это хорошо видно из таблицы 2). Типы страниц с идентификаторами 0 и 1 не определены или не используются.

Таблица 3. Типы страниц в FB

Определение в ods.h Идентификатор типа страницы Описание страницы
pag_undefined 0 Неопределенная - если страница имеет этот тип, она, вероятно, свободна
pag_header 1 Страница заголовка базы данных
pag_pages 2 Страница инвентаризации страниц (или страница инвентаризации пространства - SIP)
pag_transactions 3 Страница инвентаризации транзакций (TIP)
pag_pointer 4 Страница указателей
pag_data 5 Страница данных
pag_root 6 Корневая страница индекса
pag_index 7 Страница индекса (B-дерева)
pag_blob 8 Страница данных BLOB
pag_ids 9 Генераторы идентификаторов
pag_log 10 Информация журнала упреждающей записи

Каждая страница имеет свой заголовок, содержащий информацию о типе страницы и номере следующей страницы того же типа. Полный список параметров, которые содержит заголовок каждой страницы, можно получить, рассмотрев структуру pag в файле определений ods.h.

/* Основни заглавља страница */

typedef struct pag {

SCHAR pag_type; /* идентификатор типа странице */

SCHAR pag_flags; /* заставице странице */

USHORT pag_checksum; /* контролна сума странице: једнака је 12345 од верзије 5.0 */

ULONG pag_generation; /* генерација странице */

ULONG pag_seqno; /* WAL секвенцни број последњег ажурирања - застарело */

ULONG pag_offset; /* WAL офсет последњег ажурирања - застарело */

} *PAG;

Типови страница и њихова употреба

Размотримо сваки тип странице детаљно и упознајмо се са њиховом функцијом и информацијама које садрже. Почећемо корак по корак - од прве странице.

Свака операција са базом података почиње читањем заглавља базе података (или заглавне странице). Заглавна страница базе података је прва у свим датотекама базе података. Сходно томе, приказана је прва на слици 2 (ако замислимо да слика представља проширење датотеке базе података слева надесно, одозго надоле).

Заглавна страница садржи информације о бази података у целини. На слици 3 страница података је приказана онако како нам је IBSurgeon представља:

![](/images/IB DB structure/InterBase database structure_html_m3c792928.png)

Слика 3. Заглавна страница базе података.

Можете добити увид у садржај заглавне странице, добијањем статистике базе података. За ово можете користити алатку командне линије gstat или други погоднији алат за администрацију InterBase-а са листе у апликацији „Алати за администратора и InterBase програмере“. За више детаља о процесу добијања статистике и опису података заглавне странице погледајте поглавље „Статистика“.

Треба напоменути да заглавна страница садржи важне информације као што су величина странице, број ODS верзије (информације о томе ћете наћи у наставку), подаци о креирању базе података, информације о трансакцијама и низ различитих информација. На пример, ID имплементације чува информације о томе под којим оперативним системом је ова база података креирана.

При повезивању на базу података, InterBase сервер чита првих 1024 бајта информација са почетка датотеке и на основу прочитаних вредности одређује да ли је датотека наведена у линији повезивања InterBase база података или није. Затим сервер чита број ODS верзије са заглавне странице и величину странице у овој бази података и, ако је ODS верзија компатибилна са имплементацијом сервера, поново чита целу заглавну страницу, користећи одговарајућу величину странице, добијену из првих 1024 бајта. Након тога, остали важни параметри базе података као што су режим читања-уписа, дијалект базе података итд. се читају са заглавне странице.

На заглавној страници постоји референца на прву од показивачких страница, које чувају референце на странице података које садрже метаподатке: табелу RDB$Pages (погледајте у наставку у поглављу „Логичка структура InterBase базе података“). На слици 2 ова референца је илустрована стрелицом са натписом „Број 1. показивачке странице у бази података“. Сервер чита број 1. показивачке странице са заглавне странице и прелази на њу. Показивачка страница се састоји од уређеног низа бројева страница података које чине одређену табелу (табела се сматра SQL-објектом, описаним логичком структуром базе података). Сада можете видети како IBSurgeon тумачи показивачку страницу (погледајте слику 4):

![](/images/IB DB structure/InterBase database structure_html_3bb85660.png)

Слика 4. Показивачка страница InterBase базе података

Страница садржи вектор страница података; ови подаци чине одређену табелу у бази података. Овај вектор представља низ показивача који одговарају бројевима страница података у датотеци. Сервер чита 4-бајтни број странице података и прелази на потребну страницу података. Када пређе на 1. страницу података табеле RDB$Pages, сервер почиње да конструише интерну репрезентацију базе података која се касније користи од стране сервера за све операције са базом података. RDB$Pages чува референце не само на странице података које садрже информације о бази података, већ и на остале странице које играју улогу у обезбеђивању рада базе података.

Често помињемо ову табелу која се, строго говорећи, односи на логичку структуру базе података. Ипак, све је међусобно повезано, стога не можемо описати нешто а да се не осврнемо на нешто друго.

Један од важних типова страница је страница инвентара трансакција (TIP). Ове странице, као и све странице, састоје се од заглавља и главног дела који представља низ 2-бајтних секвенци. Секвенце описују стање трансакција у бази података (за више детаља о трансакцијама погледајте поглавље „Трансакције“).

Табела 4. Могућа стања трансакција у TIP-у

Вредност секвенце на PIP-у Значење
0 Трансакција није започета, активна или изгубљена без комита или ролбака
1 Трансакција је извршила Commit
2 Трансакција је извршила Rollback
3 Лимбо-трансакција (за 2PC)

Свака верзија записа има свој идентификатор трансакције, што омогућава истовремено извршеним трансакцијама да „сазнају“ о стању једна друге и реше конфликте током вишекорисничког рада (погледајте поглавље „Вишегенерацијска архитектура InterBase-а“ за више о верзијама записа и осталим стварима).

Заглавна страница базе података, показивачке странице и TIP спадају у „помоћне“ типове страница, које користи само сервер. Корисници InterBase-а никада експлицитно не добијају информације које оне садрже. Странице које чувају информације о алокацији страница (обично се помињу као странице инвентара страница (PIP) или странице инвентара простора (SIP)) такође спадају у помоћни тип страница. Ове странице се налазе почевши од друге, односно прва PIP иде одмах након заглавне странице, и појављују се у бази података у фиксним интервалима страница других типова. Величина ових интервала означава на колико страница других типова се PIP појављује и зависи од величине странице постављене за ову базу података. Странице инвентара страница се не воде на показивачким страницама и нису наведене у RDB$Pages. Интегритет ових страница је кључан за успешан рад целе базе јер садржај PIP-а описује стање свих осталих страница у бази података. Свака страница базе података може имати 3 стања: није алокирана, алокирана са простором, алокирана и пуна. Када постоји потреба за додатним простором за нове податке, сервер проверава PIP у циљу проналажења неалокираних страница. Ако таква страница постоји, сервер мења њено стање у алокирана са простором. Ако нема неалокираних страница, база података се проширује - додаје се нова страница података.

Пример странице података у IBSurgeon-у и података које садржи дат је на слици 5.

![](/images/IB DB structure/InterBase database structure_html_1cb26c4f.png)

Слика 5. Страница инвентара страница

Чим је страница алокирана, InterBase уписује њено стање на SIP и затим уписује саму страницу. Након тога, морамо додати ову новоформирану страницу неком великом броју страница, на пример страницама података за табелу. За то треба да упишемо референцу на ову нову страницу на последњој страници тог великог броја страница - на пример, на последњој страници података табеле. Ако је сервер прекинуо свој рад одмах након уписа на SIP, али није уписао референцу на странице, које се односе на управо алокирану страницу, онда ова страница постаје сироче. Сироче страница је физички креирана, резервисана на SIP-у, али нема референци на њу са других страница, што значи да је сервер неће моћи пронаћи и уписати податке на диск. Сироче страница је означена црвеним квадратом на слици 2. Сироче странице углавном настају као резултат неочекиваног прекида напајања сервера и „лече“ се посебним алатом за поправку базе података gfix (или FirstAID-ом) (или IBSurFirstAID-ом).

Пре разматрања страница података, треба поменути важне типове страница: генераторске и индексне странице. Генераторске странице представљају низ 4-бајтних бројева, који показују стања генератора. Заправо, генератор је обичан бројач.

На слици 6 можете видети генераторску страницу. Обратите пажњу да иако IBSurgeon приказује имена генератора, то не значи да су ова имена сачувана на генераторским страницама. То је учињено ради погодности корисника који проучава базу података. У стварности, имена генератора су сачувана у системској табели RDB$Generators.

![](/images/IB DB structure/InterBase database structure_html_7728f31.png)

Слика 6. Страница генератора (ген-идс)

Као што видите у овом примеру, база података садржи системске генераторе, који почињу префиксом RDB$, и кориснички дефинисане генераторе. Ако желите да сазнате о функцији и употреби генератора при развоју апликација за InterBase базе података, погледајте поглавље «Табеле. Примарни кључеви и генератори». Странице генератора се урачунавају заједно са осталим страницама у RDB$Pages табели.

Свака табела има најмање једну коренску страницу индекса, без обзира на то да ли има индексе или не. Ова страница садржи показиваче на странице индекса за одговарајућу табелу. Можемо рећи да је коренска страница индекса од исте важности за странице индекса као што је страница показивача за странице података. Због тога је IBSurgeon представља на сличан начин. Пример коренске странице индекса дат је на слици 7.

![](/images/IB DB structure/InterBase database structure_html_1c46b1cd.png)

Слика 7. Коренска страница индекса

Коренска страница индекса садржи листу страница на којима су смештене вредности индекса, као и информације о индексу - селективност индекса и различите заставице. За више детаља о индексима, њиховој улози и употреби у InterBase базама података погледајте поглавље «Индекси».

Странице индекса садрже директно вредности индекса, или ако је ниво индекса >0, референце на основне странице индекса. Ево примера странице индекса (слика 8).

![](/images/IB DB structure/InterBase database structure_html_m35b3f5ff.png)

Слика 8. Страница индекса (B-стабло)

Страница индекса чува упаковане вредности индексираних података. Користи се прилично сложен механизам индексације, посебно када се праве сложени индекси (који укључују више поља).

Уопштено говорећи, странице података и странице које садрже BLOB вредности чувају корисничке информације. Странице података садрже записе у корисничким табелама базе података, фрагменте записа, старе верзије, разлике између верзија, BLOB поља и тако даље. Што се тиче BLOB поља, она су повезана са записима на страницама података и садрже податке велике величине, који се не могу налазити на страници података. Референтни тип чувања BLOB вредности омогућава чување великих података.

Пример приказа странице података у IBSurgeon-у дат је на слици 9:

![](/images/IB DB structure/InterBase database structure_html_235e0c51.png)

Слика 9. Страница података

Заглавље странице података садржи тип странице, идентификатор власничке табеле (relationID). Записи се чувају на страницама података од краја странице и додељују се ближе почетку странице како се попуњавају.

Можемо се уверити у то ако погледамо индексе редова, који садрже 2 вредности - померај на страници и њену дужину. Као што видите на почетку реда налазе се записи, додељени на крају странице - на пример, први запис има померај од 8156 бајтова и дужину од 34 бајта - дакле завршава се на 8156+34=8192 бајта - на самој ивици странице (у нашем случају величина странице је 8192 бајта). Када се страница попуни (подацима одозго и индексима записа одоздо), сервер почиње да уписује нове записе и верзије старих записа на нове странице. Из механизма попуњавања странице описаног горе, лако можемо закључити зашто InterBase стручњаци снажно препоручују коришћење страница података велике величине (најмање 4096 бајтова, боље 8192). Ако креирамо табелу чији ће један запис бити прилично велике величине (на пример 10 поља VARCHAR (255)), она ће заузети, бити попуњена, више од 2550 бајтова. То значи да ће такав запис бити превелик за страницу мале величине (1024 или 2048). Очигледно је да потреба за учитавањем више страница са диска да би се прочитао један једини запис неће убрзати рад са вашом базом података. Стога се препоручује да се величина странице података редефинише приликом креирања или враћања базе података, јер је величина од 1024 бајта подешена подразумевано. Управо смо укратко размотрили главне типове страница InterBase датотека података и њихову функцију. Сада можемо прећи на виши структурни ниво.

ODS

ODS је скраћеница за On-Disk Structure, односно структуру података InterBase базе података на диску. ODS дефинише како су подаци унутар датотека базе података организовани. Дефиниција главних константи и структура података за имплементацију On-Disk структуре налази се у датотеци из скупа InterBase изворних кодова ods.h. ODS се мењао током процеса развоја InterBase-а, и када ради са одређеном базом података, сервер утврђује број ODS верзије да би знао са чиме има посла. ods.h датотека нам представља следеће верзије On-Disk структуре:

  • ODS 5 је коришћен од стране InterBase 3.3 и није подржан у верзијама изнад

  • ODS 6 и ODS 7 никада нису изашли

  • ODS 8 користи InterBase 4.0

  • ODS 9 користи InterBase 4.5 и изнад

  • ODS 10 је изашао са InterBase 6

  • ODS 11 је изашао са InterBase 7.0

Поред главних ODS верзија, постоје и мање верзије које зависе од конкретне верзије сервера базе података, који их је креирао. Главни бројеви верзије записани су у целом делу броја, који означава верзију, мањи - у разломљеном делу. На пример, сервер верзије 4.0 креира базе података, које имају ODS 8.0, а InterBase 4.2 - 8.2. Прелаз између мањих верзија одоздо нагоре извршава се аутоматски. На пример, довољно је отворити базу са ODS 8.0, креирану од стране сервера 4.0, помоћу InterBase 5.6, и ODS ове базе података ће имати верзију 8.2. Прелаз између главних верзија базе података извршава се искључиво кроз резервну копију базе података, користећи стару верзију, и враћање, користећи нову верзију сервера. Процес прелаза између верзија детаљно је описан у поглављу 1.4 «Миграција».

Важан моменат у имплементацији ODS подршке за InterBase верзије 4.x и 5.x је уназад компатибилност InterBase сервера 4.x и 5.x са верзијом за једну јединицу мањом од имплементације конкретног сервера. InterBase подржава неколико могућих ODS, и у складу са својом ODS верзијом при повезивању на конкретну базу података, бира подршку потребне ODS имплементације. Механизам одлучивања о томе коју имплементацију ODS подршке изабрати у конкретном случају назива се Y-Valve ((ц) Стива Трентона).

Једноставније речено, база података са ODS 8.x, која одговара InterBase 4.0, може се отворити у InterBase 5.x.

Комплетна табела ODS компатибилности приказана је испод:

InterBase верзија Главни ODS Мањи ODS
4.0/4.1 8.0
4.2 8.2 8.2
5.0/5.1 9.0 8.2
5.5 9.1 8.2
5.6 9.1 8.2
6.0 10.0 9.0/9.1
7.0 11.0 10.0
7.1 11.1 10.0

ODS има уназад компатибилност. Другим речима, сервер са вишом верзијом и сви његови алати ће успети да раде са базом података коју је креирао сервер ранијих верзија, али не и обрнуто. Ако покушате да отворите базу података, креирану у 6. InterBase верзији, помоћу InterBase 5.x, добићете поруку о грешци «Unsupported On-disk structure: Found ODS 10, supported ODS 9».

Опис прелаза између верзија одоздо нагоре и обрнуто погледајте у поглављу «Миграција».

ODS је веома важан за питања која се тичу резервне копије и издвајања базе података, као и враћања оштећених база података. Алати за резервну копију gbak и враћање gfix прате ODS верзију и једноставно неће радити, ако је ODS верзија базе података, којој морају да служе, већа од верзије имплементиране у њима. То значи да gbak из 4.x неће моћи да креира резервну копију базе података ако је она креирана од стране сервера 5.x, међутим лако је обрнуто.

Мост између физичке и логичке структуре базе података

Размотрили смо физичку структуру датотека базе података уопштено. Сада морамо прећи на логичку структуру базе података. Направимо мост између физичког и логичког нивоа представљања информација у бази података како не би било разграничења у појмовима и празнина у градиву. Све што је смештено на различитим страницама базе података мора бити организовано на неки начин у меморији рачунара; подаци из датотеке базе података морају бити претворени у скуп интрасерверских објеката и променљивих. Овај скуп се назива интерна слика базе података према терминологији Ен Харисон [1.. Дакле, покушаћемо да размотримо процес стварања интерне слике базе података.

  • Сервер читає 1024 байти з початку файлу, і якщо це дійсно файл бази даних InterBase, він визначає розмір сторінки цієї бази та повторно зчитує всю сторінку заголовка.

  • З заголовка сервер сторінок витягує номер сторінки покажчика, яка зберігає посилання на сторінки даних, визначаючи таблицю RDB$Pages.

  • Сервер переходить до цієї сторінки покажчика та починає читати інформацію з вказаних сторінок даних. Він заповнює першу таблицю RDB$Pages даними. Ця таблиця є чимось на кшталт мосту між фізичними об’єктами - сторінками файлів бази даних та логічними - таблицями. Структура RDB$Pages, як і інших системних таблиць, строго фіксована в InterBase.

  • Отримавши дані про розподіл сторінок за відношеннями (відношення - насправді це те саме, що й звичайні таблиці, і ми можемо подумки замінити ці поняття для спрощення), InterBase починає формувати структури даних: спочатку системні таблиці, обмеження та індекси, а потім і користувацькі об’єкти.

  • Після ініціалізації системних та користувацьких метаданих (таблиць, обмежень, індексів та інших об’єктів бази даних) InterBase повертає дескриптор цієї бази даних користувачу, який попросив відкрити базу. У дескрипторі міститься ідентифікатор, який показує InterBase, з якою базою даних працювати, оскільки кілька користувачів можуть працювати одночасно, а це означає, що може бути відкрито кілька баз даних.

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

Логічна структура бази даних InterBase

Логічна структура є досить розмитим поняттям, тому ми спробуємо поступово опанувати ключові ідеї, сподіваючись, що згодом вони стануть інтуїтивно зрозумілими. Перше, що ми розглянемо стосовно логічної структури бази даних, - це системні таблиці та їхній вміст. Системні таблиці описують систему, а також користувацькі метадані. Загалом кажучи, термін «метадані» означає «дані, що описують набір даних». Префікс «мета» означає: «описує набір». Наприклад, метамова - це мова, що описує набір мов. Метадані описують користувацькі дані, тобто таблиці, тригери, представлення, збережені процедури тощо - все, що реалізує правила зберігання та обробки інформації, заради якої створено цю конкретну базу даних.

Досить цікаво вперше дізнатися, що всі метадані - користувацькі таблиці, тригери, представлення, а також усі системні об’єкти - зберігаються в тих самих таблицях, з яких можна читати та записувати дані за допомогою звичайних SQL-запитів. Ці таблиці «візуально» відрізняються лише тим, що їхні назви починаються з RDB$. Ці 4 символи зарезервовані для назв системних об’єктів. Жодна користувацька таблиця, стовпець чи інший об’єкт не має права мати назви, що починаються з цих символів. Формально ви можете створити таблицю, назва якої починається із зарезервованих символів, але документація InterBase не рекомендує цього робити.

Виникає питання: якщо дані про структуру бази даних зберігаються в тих самих таблицях, що й користувацькі дані, то де зберігається інформація про таблиці, що описують таблиці? Класичний приклад проблеми «курки та яйця» - як одне могло з’явитися раніше за інше, якщо вони взаємозалежні? Відповідь полягає в тому, що системні таблиці в їхньому примітивному стані зафіксовані в початкових кодах InterBase і автоматично відкриваються під час створення бази даних у певному порядку. Ми вже говорили про таблицю RDB$Pages, яка зіставляє фізичні сторінки у файлах бази даних із певними об’єктами цієї бази. Структуру цієї таблиці наведено нижче:

Таблиця 5. Системна таблиця RDB$Pages

Назва стовпця Тип даних Опис
RDB$PAGE_NUMBER INTEGER Номер фізичної сторінки
RDB$RELATION_ID SMALLINT Ідентифікатор таблиці, для якої виділено сторінку
RDB$PAGE_SEQUENCE INTEGER Номер цієї сторінки
RDB$PAGE_TYPE SMALLINT Тип сторінки - див. таблицю 3

Кожна сторінка даних пов’язана з певною таблицею. Цей зв’язок підтримується полем RDB$RELATION_ID, де зберігається посилання на таблицю. Як описано вище, у процесі побудови внутрішнього образу бази даних сервер створює цю таблицю та заповнює її даними за заданим алгоритмом. Якщо бути точним, на момент побудови внутрішнього образу бази даних RDB$Pages - це не таблиця, а просто файл даних певного формату, відомого InterBase. За фіксованим алгоритмом сервер читає дані з цього файлу та створює таблицю - RDB$Relations - яка є важливою для всієї бази даних. Ця таблиця описує всі таблиці бази даних. Якщо виконати SQL-запит:

SELECT * from RDB$Relations

щоб дізнатися, на які таблиці містить посилання RDB$Relations, ми побачимо, що вона містить RDB$Pages і саму себе. Очевидно, що в цьому випадку сервер трохи хитрує, підставляючи ці та інші системні таблиці в RDB$Relations заднім числом, таким чином легітимізуючи їх. Сервер реєструє їх як «звичайні» таблиці, куди може додавати або видаляти записи. Іншими словами, надає стандартний SQL-інтерфейс для роботи з метаданими.

І може виникнути цілком розумне питання - навіщо розробникам InterBase пристосовувати свої системні дані до користувацького інтерфейсу? Адже внутрішні механізми доступу та операцій читання були б швидшими. Звісно, є великий сенс у наданні універсального механізму роботи з таблицями, що описують метадані.

Справа в тому, що логічна структура бази даних складається не лише з таблиць, а й з інших об’єктів. В InterBase існують такі об’єкти:

  • Таблиця

  • Представлення

  • Тригер

  • Обчислюване поле

  • Перевірка

  • Процедура

  • Індекс за виразом

  • Виняток

  • Користувач

  • Поле

  • Індекс

  • Функція, визначена користувачем (UDF)

Ми ще не знаємо напевно функцій деяких об’єктів, але точно знаємо, що всі вони мають бути описані та збережені в певному вигляді, зручному для користувача та для доступу з ядра InterBase. Найкраще було б зберігати ці об’єкти в системних таблицях. Їхнє додавання та модифікація виконуються SQL-запитами. Розумне рішення, чи не так? Реалізація сервера повністю відокремлена від конкретної бази даних - усі взаємозв’язки описані SQL та його розширеннями - мовою збережених процедур і тригерів.

Отже, усі серверні об’єкти зберігаються в таблицях. Кожен тип об’єктів має таблицю, що описує всі екземпляри, описані в базі даних. Наприклад, для тригерів існує таблиця RDB$Triggers, для збережених процедур - RDB$Procedures, представлення описані в таблиці RDB$Relations.

Розглянемо детально структуру останньої таблиці, що описує всі таблиці та представлення в базі даних. Структуру таблиці RDB$RELATIONS взято з Language Reference для InterBase 6 і наведено нижче в таблиці 6.

Таблиця 6. Системна таблиця RDB$Relations

Назва стовпця Тип даних Довжина Опис
RDB$VIEW_BLR BLOB 80 BLR: для представлень містить BLR (Binary Language Representation) запиту, який InterBase виконує щоразу під час звернення до представлення.
RDB$VIEW_SOURCE BLOB 80 Текст: для представлень містить код SQL-запиту, що реалізує це представлення.
RDB$_DESCRIPTION BLOB 80 Користувацький опис таблиці або представлення
RDB$RELATION_ID SMALLINT Містить внутрішній ідентифікатор таблиці/представлення
RDB$SYSTEM_FLAG SMALLINT Визначає тип таблиці: користувацькі дані - 0; системна інформація > 0.
RDB$DBKEY_LENGTH SMALLINT Довжина db$key
RDB$FORMAT SMALLINT Зарезервовано для внутрішнього використання InterBase. Містить лічильник модифікацій метаданих для даної таблиці.
RDB$FIELD_ID SMALLINT Кількість полів у таблиці.
RDB$RELATION_NAME CHAR 31 Унікальна назва таблиці.

В описі цієї системної таблиці ми бачимо абревіатуру BLR. Щоб зрозуміти, що це таке, зробимо екскурс у SQL. Як відомо, представлення, тригери та збережені процедури - це код, написаний розширенням мови SQL (для кожного сервера СКБД існують власні розширення). Він близький до людської мови, що дозволяє легко складати запити. Але InterBase, очевидно, перекладає його на щось більш «машинне» - а саме в BLR (Binary Language Representation). Будь-який запит, представлення, тригер, збережена процедура завжди перекладаються в BLR, а потім передаються в ядро InterBase для виконання.

BLR

BLR је посебан језик који се користи као посредна веза између SQL кода који програмер пише и машинског кода који сервер прихвата. Нико не пише директно у BLR-у - то би било прилично тешко јер се у овом језику, ради највеће могуће брзине извршавања, користи такозвани повратни пољски запис. Ево малог примера:

blr_begin,

     blr\_assignment,

        blr\_field, 0, 7, 'D','A','T','E','I','Z','M',

        blr\_variable, 1,0,

     blr\_assignment,

        blr\_field, 0, 4, 'R','A','T','E',

        blr\_variable, 0,0,

     blr\_block,

BLR за ваше упите, процедуре, тригере и друге тригере формира посебан препроцесор који је део језгра сервера. Као што је приказано у табели 7, за погледе се чува њихов текст (почетни) поглед, као и компиловани поглед, односно BLR. Када се позива било који објекат који има BLR, сервер извршава бинарни код објекта и не тумачи почетни текст тих објеката сваки пут, што омогућава убрзавање извршавања сложених упита.

Хијерархија објеката у InterBase-у

Да бисмо имали јасну представу о томе шта представљају објекти базе података, покушаћемо да направимо хијерархију објеката базе података према принципу „ко садржи и шта“. Физичке странице датотека базе података су прве које морају бити укључене у нашу хијерархију као најнижи ниво организације података. Затим долазе табеле као основни објекти који описују све остале типове објеката. Табеле описују ускладиштене процедуре, тригере, израчуната поља, валидације, изразне индексе, изузетке и тако даље. Обратите пажњу - само описују! Табеле садрже само декларације и дефиниције ових објеката, а објекти се имплементирају кроз BLR. Стога можемо представити табеле у облику оквира који подржава све остале објекте базе података. BLR ће бити на дну оквира као слој имплементације, затим тригери, ускладиштене процедуре, изразни индекси и погледи.

Да бисмо умирили стручњаке за унутрашњу структуру InterBase-а, који би могли приговорити да се BLR многих објеката (као што су погледи) чува у системским табелама, прокоментарисаћемо да је такав однос прилично тешко изразити на слици и да ћемо га ради поједностављења изоставити. Шема нема за циљ да апсолутно тачно рекреира међузависности објеката базе података; она само илуструје њихову тесну међусобну повезаност.

Чињеница да су ови типови објеката директно повезани са BLR-ом, који их имплементира без икакве посредне логике, их уједињује. Изузетке треба издвојити посебно - они представљају посебне типове грешака које дефинише корисник. Изузеци се обрађују на нивоу језгра InterBase-а и стога немају BLR. Такви типови ограничења као што су провере (checks) смештени су изнад тригера јер у стварности тригери имплементирају логику ограничења и провера.

Хијерархија објеката логичке и физичке структуре базе података приказана је на слици 2.

Слика 10. Објекти логичке структуре InterBase базе података

Наравно, ова шема описује логичку структуру и међусобне везе објеката у бази података само приближно и даје општу представу о њој. Свако ко жели да проучи структуру метаподатака InterBase базе података може извршити реинжењеринг системских табела базе података и размотрити све међусобне везе између њених објеката, као и обратити се документацији и изворним кодовима InterBase-а. Ова табела приказује само главне објекте базе података. Хајде да укратко опишемо главне функције које ови објекти обављају у бази података.

Табеле - главни објекат који садржи корисничке и системске податке. Табела има јединствено име и садржи скуп именованих поља. Корисник може смештати податке, извлачити их и мењати у табелама. Можемо рећи да је табела слична обичним папирним табелама које се цртају ручно.

Тригери - извршни делови кода који се користе за имплементацију додатних радњи приликом операција над подацима. Тригери се извршавају пре или после операција уметања, измене или брисања и омогућавају реализацију замене вредности у новокреираним записима и многе друге ствари.

Ускладиштена процедура је моћан алат за имплементацију пословне логике на нивоу базе података. Пошто се извршава на нивоу сервера, ради веома брзо и омогућава извршавање скупа операција над скуповима података. Ускладиштене процедуре InterBase-а враћају стандардне SQL скупове података над којима се могу извршавати све SQL операције, укључујући и унификацију са другим табелама.

Погледи су компиловани SQL упити који се извршавају на серверу. Погледи омогућавају организовање скупова података, преносећи део пословне логике на сервер.

Валидације су ограничења постављена на вредности поља у табели. На пример, можемо назначити да дато поље прихвата само позитивне вредности. Ограничења на вредности поља имплементирана су тригерима и омогућавају ефикасну контролу референцијалног интегритета на нивоу базе података. Обично се ограничења користе да би се спречило уношење погрешних вредности у табелу.

Корисници - InterBase нам омогућава да имамо више корисника за рад са базом података и да расподелимо права приступа различитим објектима базе података међу њима. На тај начин можемо контролисати дозволе за одређене операције над базом података.

Кориснички дефинисане функције (UDF) - функције које дефинише корисник. То је једна од најмоћнијих могућности InterBase-а која нам омогућава да проширимо стандардни SQL интерфејс сопственим функцијама. На пример, функције за рад са низовима као што је UPPER (постављање свих симбола у велика слова), имплементиране су у стандардној UDF библиотеци која је укључена у InterBase пакет. Захваљујући могућности креирања сопствених UDF функција, програмери могу проширити функционалност InterBase-а практично било којим функцијама. За креирање UDF функција можемо користити било које програмско окружење које омогућава креирање динамичких библиотека (Visual C++, C++ Builder, Delphi итд.).

Закључак

У овом поглављу смо први пут размотрили питања о имплементацији чувања и обраде података унутар InterBase базе података. Нажалост, не можемо дати кратак преглед ове теме без позивања на велики број термина и нетачних аналогија. Ако бисмо детаљније описали физичку и логичку структуру базе података, морали бисмо се позвати на изворне кодове InterBase-а, али то би била друга књига.

Ипак, мислимо да би било корисно за сваког програмера да се упозна са садржајем производа који користи свакодневно.

Библиографија

  1. „The On-Disk Structure of InterBase“ од Ann.W.Harrison

  2. „Space Management in InterBase“ од Ann W.Harrison

  3. „Structure of a Data Page“ од Paul Beach (са захвалношћу Dave Schnepper-у и Deej Bredenberg-у)