С. Д. Кузнецов
Институт системного программирования РАН, Ассоциация пользователей ОС UNIX (SUUG), Московская секция ACM SIGMOD, kuz@ivann.delta.msk.su
В любом деле требуется правильно подобранный инструмент
- 2.1. Структуры файлов
- 2.2. Именование файлов
- 2.3. Защита файлов
- 2.4. Режим многопользовательского доступа
Несмотря на то, что технологии баз данных становятся все более распространенными в практике, многие разработчики прикладных систем, администраторы баз данных и конечные пользователи недостаточно хорошо понимают, что такое современные базы данных и системы управления базами данных (СУБД). Сказывается отсутствие или поверхностный уровень соответствующих курсов в высших учебных заведениях, практическое отсутствие литературы на русском языке и, наконец, привлечение к деятельности, связанной с использованием баз данных, специалистов, которые ранее работали в других областях. Обучение, проводимое коммерческими компаниями, обычно ориентируется на конкретные программные продукты и не может компенсировать отсутствие базовой подготовки.
Чтобы помочь читателям нашего журнала лучше ориентироваться в современном мире баз данных и, в частности, дать им возможность читать и понимать более специальную литературу (в том числе и статьи, которые печатаются в этом журнале), мы решили печатать с продолжением цикл лекций, обеспечивающих введение в системы управления базами данных. Эти лекции требуют самой минимальной подготовки: необходимо лишь понимать смысл распространенных математических и программистских терминов. Вместе с тем, лекции ориентированы на заинтересованного читателя, для которого важно получить базовые знания (или обновить их) и который готов потратить на это некоторое количество времени и сил.
В некотором роде, к циклу лекций можно относиться как к заочному учебному курсу. Мы готовы отвечать (индивидуально или со страниц журнала) на вопросы читателей, а также время от времени будем предлагать вопросы и задания, которые помогут вам проверить, насколько хорошо вы поняли предложенный ранее материал.
По причине широкого распространения реляционных СУБД и очевидного сохранения этого явления в ближайшем будущем, основной темой лекций являются различные аспекты реляционных баз данных. Вместе с тем, многие рассматриваемые вопросы являются более общими и актуальны в связи с более отдаленным будущем, когда на смену реляционным базам данных придет какой-либо другой подход.
Цикл лекций будет состоять из семи частей. В первой, вводной части будет рассмотрен общий смысл понятий базы данных (БД) и СУБД и приведено их сравнение с понятиями файловой системы и системы управления файлами. Будут описаны основные функции и типовая организация СУБД. В заключение вводной части будут сформулированы основные понятия реляционного подхода к организации БД и введена соответствующая терминология.
Во второй части цикла детально рассматриваются реляционная модель данных и ее составные части - структурная, манипуляционная и целостная. В классической форме будут определены реляционная алгебра и реляционное исчисление, два эквивалентных механизма, на которых базируются современные языки манипулирования базами данных.
Третья часть цикла посвящается проектированию реляционных БД. Будут описаны два подхода: на основе пошаговой нормализации исходного универсального отношения и с использованием семантических моделей данных, из которых наиболее распространена практически модель "сущность-связь".
В четвертой части рассматриваются методы внутренней организации многопользовательских реляционных СУБД. Будут проанализированы методы организации внешней памяти реляционных БД и специальных служебных структур внешней памяти-индексов, служащих для оптимизации выполнения запросов к БД. Далее мы введем понятие транзакции и рассмотрим методы управления транзакциями на основе разных подходов к синхронизации параллельного доступа к БД. Наконец, мы остановимся на способах поддержания надежного хранения БД за счет ведения журнала изменений БД.
Пятая часть цикла посвящена языку SQL - наиболее распространенному языку реляционных БД. Будут рассмотрены наиболее важные проблемы реализации SQL, включая проблемы оптимизации запросов.
В шестой части рассматриваются некоторые особенности современных реляционных СУБД: интерфейсы доступа к БД высокого уровня и языки прототипирования прикладных информационных систем; архитектура "клиент-сервер", позволяющая использовать СУБД в неоднородных локальных вычислительных средах, и связанная с этим проблема преобразования представлений данных.
Наконец, седьмая часть цикла посвящена рассмотрению проблем и решений распределенных реляционных СУБД, позволяющих хранить одну логически связанную БД в нескольких узлах вычислительной сети.
Как мы уже отмечали, литературы на русском языке, посвященной тематике СУБД, очень мало. К числу лучших относятся книги К. Дейта "Введение в системы баз данных" (Наука, 1980) и "Руководство по реляционной СУБД DB2" (Финансы и статистика, 1988), а также книга Дж. Ульмана "Основы систем баз данных" (Финансы и статистика, 1983). Хотя эти книги несколько устарели (на английском языке вышло уже несколько дополненных изданий), их стоит читать. Заметим, что практически одновременно с выходом в свет этого номера журнала должно появиться новое издание книги Дейта, являющееся переводом пятого американского издания.
Введение в СУБД: Часть 1
Файловые системы и базы данных, или
В любом деле требуется правильно подобранный инструмент
Думаю, что многим читателям эта лекция покажется тривиальной. Вот еще, вздумали объяснять, как устроены и как используются магнитные диски и как устроена файловая система ОС UNIX. Однако поверьте, что очень часто довольно трудно понять, какой механизм управления данными во внешней памяти необходим и достаточен для решения конкретной прикладной задачи. Если раньше приходилось сталкиваться с ситуацией, когда возможности файлов переоценивались, то теперь сплошь да рядом применяют базы данных в случаях, для которых вполне достаточно файлов. Поэтому кажется полезным еще раз перечислить возможности и альтернативные решения файловых систем, показать наиболее типичные области их применения и отметить те ситуации, когда эти возможности оказываются недостаточными для организации прикладных систем.
1. Численные и информационные прикладные системы
Во всей истории вычислительной техники можно проследить две основных области ее использования. Первая область - применение вычислительной техники для выполнения численных расчетов, которые слишком долго или вообще невозможно производить вручную. Развитие этой области способствовало интенсификации методов численного решения сложных математических задач, развитию класса языков программирования, ориентированных на удобную запись численных алгоритмов, становлению обратной связи с разработчиками новых архитектур ЭВМ.
Вторая область, которая непосредственно относится к теме наших лекций, - это использование средств вычислительной техники в автоматических или автоматизированных информационных системах. В самом широком смысле информационная система представляет собой программно-аппаратный комплекс, функции которого состоят в надежном хранении информации в памяти компьютера, выполнении специфических для данного приложения преобразований информации и/или вычислений, предоставлении пользователям удобного и легко осваиваемого интерфейса. Обычно такие системы имеют дело с большими объемами информации, и эта информация имеет достаточно сложную структуру. Классическими примерами информационных систем являются банковские системы, системы резервирования авиационных или железнодорожных билетов, мест в гостиницах и т. д.
Вторая область использования вычислительной техники возникла несколько позже первой. Это связано с тем, что на заре вычислительной техники возможности компьютеров по хранению информации были очень ограниченными. Говорить о надежном и долговременном хранении информации можно только при наличии запоминающих устройств, сохраняющих информацию после выключения электрического питания. Оперативная (основная) память компьютеров этим свойством обычно не обладает. В первых компьютерах использовались два вида устройств внешней памяти - магнитные ленты и барабаны. Емкость магнитных лент была достаточно велика, но по своей физической природе они обеспечивали последовательный доступ к данным. Магнитные же барабаны (они больше всего похожи на современные магнитные диски с фиксированными головками) давали возможность произвольного доступа к данными, но были ограниченного размера.
Эти ограничения не являлись слишком существенными для чисто численных расчетов. Даже если программа должна обработать (или произвести) большой объем информации, при программировании можно продумать расположение этой информации во внешней памяти (например, на последовательной магнитной ленте), обеспечивающее эффективное выполнение этой программы.
Но для информационных систем, в которых потребность в текущих данных определяется конечным пользователем, наличие только магнитных лент и барабанов неудовлетворительно. Представьте себе покупателя билета, который, стоя у кассы, должен дождаться полной перемотки магнитной ленты. Одним из естественных требований к таким системам является удовлетворительная средняя скорость выполнения операций.
Как кажется, именно требования нечисленных приложений вызвали появление съемных магнитных дисков с подвижными головками, что явилось революцией в истории вычислительной техники. Эти устройства внешней памяти обладали существенно большей емкостью, чем магнитные барабаны, обеспечивали удовлетворительную скорость доступа к данным в режиме произвольной выборки, а возможность смены дискового пакета на устройстве позволяла иметь практически неограниченный архив данных.
С появлением магнитных дисков началась история систем управления данными во внешней памяти. До этого каждая прикладная программа, которой требовалось хранить данные во внешней памяти, сама определяла расположение каждой порции данных на магнитной ленте или барабане и выполняла обмены между оперативной памятью и устройствами внешней памяти с помощью программно-аппаратных средств низкого уровня (машинных команд или вызовов соответствующих программ операционной системы). Такой режим работы не позволяет или очень затрудняет поддержание на одном внешнем носителе нескольких архивов долговременно хранимой информации. Кроме того, каждой прикладной программе приходилось решать проблемы именования частей данных и структуризации данных во внешней памяти.
2. Файловые системы
Историческим шагом явился переход к использованию централизованных систем управления файлами. С точки зрения прикладной программы, файл - это именованная область внешней памяти, в которую можно записывать и из которой можно считывать данные. Правила именования файлов, способ доступа к данным, хранящимся в файле, и структура этих данных зависят от конкретной системы управления файлами и, возможно, от типа файла. Система управления файлами берет на себя распределение внешней памяти, отображение имен файлов в соответствующие адреса во внешней памяти и обеспечение доступа к данным.
Первая получившая широкое распространение файловая система была разработана фирмой IBM для серии компьютеров 360. К настоящему времени она очень устарела, и мы не будем рассматривать детали ее организации. Заметим лишь, что в этой системе поддерживались как чисто последовательные, так и индексно-последовательные файлы, а реализация во многом опиралась на возможности только появившихся к этому времени контроллеров управления дисковыми устройствами. Если учесть к тому же, что понятие файла в OS/360 являлось базовой абстракцией, которому соответствовал любой внешний объект, включая внешние устройства, то работать с файлами на уровне пользователя было очень неудобно. Требовался целый ряд громоздких и перегруженных деталями конструкций. Все это хорошо знакомо программистам среднего и старшего поколения, которые прошли через использование отечественных аналогов компьютеров IBM.
Поэтому дальше мы будем говорить о более современных организациях файловых систем и начнем со структур файлов.
2.1. Структуры файлов
Прежде всего, практически во всех современных компьютерах основными устройствами внешней памяти являются магнитные диски с подвижными головками, и именно они служат для хранения файлов. Такие магнитные диски представляют собой пакеты магнитных пластин (поверхностей), между которыми на одном рычаге двигается пакет магнитных головок. Шаг движения пакета головок является дискретным, и каждому положению пакета головок логически соответствует цилиндр магнитного диска. На каждой поверхности цилиндр "высекает" дорожку, так что каждая поверхность содержит число дорожек, равное числу цилиндров. При разметке магнитного диска (специальном действии, предшествующем использованию диска) каждая дорожка размечается на одно и то же количество блоков таким образом, что в каждый блок можно записать по максимуму одно и то же число байтов. Таким образом, для выполнения обмена с магнитным диском на уровне аппаратуры нужно указать номер цилиндра, номер поверхности, номер блока на соответствующей дорожке и число байтов, которое нужно записать или прочитать от начала этого блока.
Однако эта возможность обмениваться с магнитными дисками порциями меньше объема блока в настоящее время не используется в файловых системах. Это связано с двумя обстоятельствами. Во-первых, аппаратура управления дисками является электронно-механической, и при выполнении обмена с диском выполняются три основных действия: подвод головок к нужному цилиндру, поиск на дорожке нужного блока и собственно обмен с этим блоком. Из всех этих действий в среднем наибольшее время занимает первое, механическое действие. Поэтому существенный выигрыш в суммарном времени обмена за счет считывания или записывания только части блока получить практически невозможно. Во-вторых, для того чтобы работать с частями блоков, файловая система должна обеспечить соответствующего размера буфера оперативной памяти, что существенно усложняет распределение оперативной памяти.
Поэтому во всех современных файловых системах явно или неявно выделяется некоторый базовый уровень. На этом уровне обеспечивается работа с файлами, состоящими из блоков, прямо адресуемых в адресном пространстве файла. Размер этих логических блоков файла совпадает или кратен размеру физического блока диска и обычно выбирается равным размеру страницы виртуальной памяти, поддерживаемой аппаратурой компьютера совместно с операционной системой.
В некоторых файловых системах базовый уровень доступен пользователю, но более часто прикрывается некоторым более высоким уровнем, стандартным для пользователей. Распространены два основных подхода.
При первом подходе, применяемом, например, в файловых системах операционных систем фирмы DEC RSX и VMS, пользователи представляют файл как последовательность записей. Каждая запись - это байтовая последовательность постоянного или переменного размера. Записи можно читать или записывать последовательно или позиционировать файл на запись с указанным номером.
Некоторые файловые системы позволяют разбивать записи на поля и объявлять некоторые поля ключами записи. В таких файловых системах можно потребовать выборку записи из файла по ее заданному ключу. Естественно, что в этом случае файловая система поддерживает в том же (или другом, служебном) базовом файле дополнительные невидимые пользователю служебные структуры данных. Распространенные способы организации ключевых файлов основываются на технике хэширования и B-деревьев. Существуют и многоключевые способы организации файлов.
Второй подход, ставший распространенным вместе с операционной системой UNIX, состоит в том, что любой файл представляется как последовательность байтов. Из файла можно прочитать указанное число байтов, либо начиная с его начала, либо предварительно произведя его позиционирование на байт с указанным номером. Аналогично, можно записать указанное число байтов в конец файла, либо предварительно выполнив позиционирование файла. Заметим, что, тем не менее, во всех разновидностях файловых систем ОС UNIX поддерживается базовое блочное представление файла, которое скрыто от пользователей.
Конечно, для обоих подходов можно обеспечить набор преобразующих функций, приводящих представление файла к некоторому другому виду. Один из примеров - наличие стандартной файловой среды системы программирования на языке Си в операционных системах фирмы DEC.
2.2. Именование файлов
Все современные файловые системы поддерживают многоуровневое именование файлов за счет поддержания во внешней памяти дополнительных файлов со специальной структурой - каталогов. Каждый каталог содержит имена каталогов и/или файлов, содержащихся в данном каталоге. Таким образом, полное имя файла состоит из списка имен каталогов плюс имя файла в каталоге, непосредственно указывающем на данный файл. Разница между способами именования файлов в разных файловых системах состоит в том, с чего начинается эта цепочка имен.
Имеются два крайних варианта. Во многих системах управления файлами требуется, чтобы каждый архив файлов (полное дерево справочников) целиком располагался на одном дисковом пакете (или логическом диске, разделе физического дискового пакета, представляемом с помощью средств операционной системы как отдельный диск). В этом случае полное имя файла начинается с имени дискового устройства, на котором установлен соответствующий диск. Такой способ именования используется в файловых системах фирмы DEC, очень близко к этому находятся и файловые системы персональных компьютеров. Можно назвать эту организацию поддержанием изолированных файловых систем.
Другой крайний вариант был реализован в файловых системах операционной системы Multics. Эта система заслуживает отдельного большого разговора, в ней был реализован целый ряд оригинальных идей, но мы остановимся только на особенностях организации архива файлов. В файловой системе Miltics пользователи представляли всю совокупность каталогов и файлов как единое дерево. Полное имя файла начиналось с имени корневого каталога, и пользователь не обязан был заботиться об установке на дисковое устройство каких-либо конкретных дисков. Сама система, выполняя поиск файла по его имени, запрашивала оператора об установке необходимых дисков. Такую файловую систему можно назвать полностью централизованной.
Конечно, во многом централизованные файловые системы удобнее изолированных: система управления файлами принимает на себя больше рутинной работы. Но в таких системах возникают существенные проблемы, если кому-то требуется перенести поддерево файловой системы на другую вычислительную установку.
Компромиссное решение применено в файловых системах ОС UNIX. На базовом уровне в этих файловых системах поддерживаются изолированные архивы файлов. Один из этих архивов объявляется корневой файловой системой. После запуска системы можно "смонтировать" корневую файловую систему и ряд изолированных файловых систем в одну общую файловую систему. Технически это производится с помощью создания в корневой файловой системе специальных пустых каталогов. Специальный системный вызов mount ОС UNIX позволяет подключить к одному из этих пустых каталогов корневой каталог указанного архива файлов. После монтирования общей файловой системы именование файлов производится так же, как если бы она с самого начала была централизованной. Если учесть, что обычно монтирование файловой системы производится при раскрутке системы, то пользователи ОС UNIX обычно и не задумываются об исходном происхождении общей файловой системы.
2.3. Защита файлов
Поскольку файловые системы являются общим хранилищем файлов, принадлежащих, вообще говоря, разным пользователям, системы управления файлами должны обеспечивать авторизацию доступа к файлам. В общем виде подход состоит в том, что по отношению к каждому зарегистрированному пользователю данной вычислительной системы для каждого существующего файла указываются действия, которые разрешены или запрещены данному пользователю. Существовали попытки реализовать этот подход в полном объеме. Но это вызывало слишком большие накладные расходы как по хранению избыточной информации, так и по использованию этой информации для контроля правомочности доступа.
Поэтому в большинстве современных систем управления файлами применяется подход к защите файлов, впервые реализованный в ОС UNIX. В этой ОС каждому зарегистрированному пользователю соответствует пара целочисленных идентификаторов: идентификатор группы, к которой относится этот пользователь, и его собственный идентификатор в группе. При каждом файле хранится полный идентификатор пользователя, который создал этот файл, и фиксируется, какие действия с файлом может производить его создатель, какие действия с файлом доступны для других пользователей той же группы и что могут делать с файлом пользователи других групп. Эта информация очень компактна, требующиеся при проверке действия невелики, а такой способ контроля доступа удовлетворителен в большинстве случаев.
2.4. Режим многопользовательского доступа
Последнее, на чем мы остановимся в связи с файлами, это способы их использования в многопользовательской среде. Если операционная система поддерживает многопользовательский режим, вполне реальна ситуация, когда два или более пользователя одновременно пытаются работать с одним и тем же файлом. Если все пользователи собираются только читать файл, ничего страшного не произойдет. Но если хотя бы один из них будет изменять файл, для корректной работы этих пользователей требуется взаимная синхронизация.
В системах управления файлами обычно применялся следующий подход. В операции открытия файла (первой и обязательной операции, с которой должен начинаться сеанс работы с файлом) среди прочих параметров указывался режим работы (чтение или изменение). Если к моменту выполнения этой операции от имени некоторого пользовательского процесса A файл уже находился в открытом состоянии от имени некоторого другого процесса B, причем файл был открыт в режиме, который несовместим с желаемым режимом открытия (совместимы только режимы чтения), то в зависимости от особенностей системы процессу A либо сообщалось о невозможности открытия файла в желаемом режиме, либо он блокировался до тех пор, пока в процессе B не выполнялась операция закрытия файла.
Заметим, что в ранних версиях файловой системы ОС UNIX вообще не были предусмотрены какие бы то ни было средства синхронизации параллельного доступа к файлам. Операция открытия файла выполнялась всегда для любого существующего файла, если пользователь, от имени которого выполнялся процесс, имел соответствующие права доступа. При совместной работе синхронизацию приходилось производить вне файловой системы (и специальных средств для этого ОС UNIX не предоставляла). В современных реализациях файловых систем ОС UNIX по выбору поддерживается синхронизация при открытии файлов. Кроме того, существует возможность синхронизации нескольких процессов, параллельно модифицирующих один и тот же файл. Для этого введен специальный механизм синхронизационных блокировок диапазонов адресов открытого файла.
3. Области применения файлов
После этого краткого экскурса в историю и возможности систем управления файлами рассмотрим возможные области их применения. Конечно, прежде всего файлы применяются для хранения текстовых данных: документов, текстов программ и т. д. Такие файлы обычно образуются и модифицируются с помощью различных текстовых редакторов. Структура текстовых файлов обычно очень проста: это либо последовательность записей, содержащих строки текста, либо последовательность байтов, среди которых встречаются специальные символы (например, символы конца строки).
Файлы с текстами программ являются входными параметрами компиляторов, которые, в свою очередь, формируют файлы, содержащие объектные модули. С точки зрения файловой системы, объектные файлы также обладают абсолютно стандартной структурой - последовательности записей или байтов. Система программирования накладывает на эту структуру более сложную и специфичную для этой системы структуру объектного модуля. Подчеркнем, что логическая структура объектного модуля неизвестна файловой системе, эта структура поддерживается программами системы программирования.
Аналогично обстоит дело с файлами, формируемыми редакторами связей (компоновщиками выполняемых программ) и содержащими образы выполняемых программ. Логическая структура таких файлов остается известной только редактору связей и программе-загрузчику, являющейся компонентом операционной системы.
Заметим, что в отмеченных выше случаях вполне достаточно тех средств защиты файлов и синхронизации параллельного доступа, которые обеспечивают системы управления файлами. Очень редко возникает потребность параллельной модификации файлов, и как правило, каждый пользователь может обойтись своей частной копией.
Другими словами, файловые системы обычно обеспечивают хранение слабо структурированной информации, оставляя дальнейшую структуризацию прикладным программам. В перечисленных выше случаях использования файлов это даже хорошо, потому что при разработке любой новой прикладной системы, опираясь на простые, стандартные и сравнительно дешевые средства файловой системы, можно реализовать те структуры хранения, которые наиболее естественно соответствуют специфике данной прикладной области.
4. Потребности информационных систем
Однако для информационных систем ситуация коренным образом отличается. Эти системы главным образом ориентированы на хранение, выбор и модификацию постоянно хранимой информации. Структура информации обычно очень сложна, и хотя структуры данных различны в разных информационных системах, между ними часто бывает много общего. На начальном этапе использования вычислительной техники проблемы структуризации данных решались индивидуально в каждой информационной системе. Производились необходимые надстройки (библиотеки программ) над файловыми системами, подобно тому, как это делается в компиляторах, редакторах и т. д.
Но поскольку в информационных системах требуется поддержка сложных структур данных, эти индивидуальные средства управления данными составляли существенную часть информационных систем, практически повторяясь (как программные компоненты) от одной системы к другой. Стремление выделить общую часть информационных систем, ответственную за управление сложно структурированными данными явилось, на наш взгляд, первой побудительной причиной создания СУБД, которая, возможно, могла бы представлять некоторую общую библиотеку программ, доступную каждой информационной системе.
Однако очень скоро стало понятно, что невозможно обойтись такой общей библиотекой программ, реализующей над стандартной базовой файловой системой более сложные методы хранения данными. Поясним это на примере. Предположим, что мы хотим реализовать простую информационную систему, поддерживающую учет сотрудников некоторой организации. Система должна выдавать списки сотрудников в соответствии с указанными номерами отделов, поддерживать регистрацию перевода сотрудника из одного отдела в другой, приема на работу новых сотрудников и увольнения работающих. Для каждого отдела должна поддерживаться возможность получения имени руководителя этого отдела, общей численности отдела, общей суммы выплаченной в последний раз зарплаты и т. д. Для каждого сотрудника должна поддерживаться возможность выдачи номера удостоверения по полному имени сотрудника, выдачи полного имени по номеру удостоверения, получения информации о текущем соответствии занимаемой должности сотрудника и о размере зарплаты.
Предположим, что мы решили реализовать эту информационную систему на основе файловой системы и пользоваться при этом одним файлом, расширив базовые возможности файловой системы за счет специальной библиотеки функций. Поскольку минимальной информационной единицей в нашем случае является сотрудник, естественно потребовать, чтобы в этом файле содержалась одна запись для каждого сотрудника. Очевидно, что поля таких записей должны содержать полное имя сотрудника (СОТР_ИМЯ), номер его удостоверения (СОТР_НОМЕР), информацию о его соответствии занимаемой должности (СОТР_СТАТ - для простоты, "да" или "нет"), размер зарплаты (СОТР_ЗАРП), номер отдела (СОТР_ОТД_НОМЕР). Поскольку мы хотим ограничиться одним файлом, эта же запись должна содержать имя руководителя отдела (СОТР_ОТД_РУК).
Для выполнения функций нашей информационной системы требуется возможность многоключевого доступа к этому файлу по уникальным ключам (недублируемым в разных записях) СОТР_ИМЯ и СОТР_НОМЕР. Кроме того, должна обеспечиваться возможность выбора всех записей с общем заданным значением СОТР_ОТД_НОМЕР, то есть доступ по неуникальному ключу. Чтобы получить численность отдела или общий размер зарплаты, информационная система должна будет каждый раз выбирать все записи о сотрудниках отдела и подсчитывать соответствующие общие значения.
Таким образом, для реализации даже такой простой системы на базе файловой системы, во-первых, требуется создание достаточно сложной надстройки, обеспечивающей многоключевой доступ к файлам, и во-вторых, неизбежны существенная избыточность хранения (для каждого сотрудника данного отдела повторяется имя руководителя отдела) и выполнение массовой выборки и вычислений для получения сводной информации об отделах. Кроме того, если в ходе эксплуатации системы возникнет потребность, например, выдавать списки сотрудников, получающих заданную зарплату, то придется либо полностью просматривать файл, либо реструктуризовывать его, объявляя ключевым поле СОТР_ЗАРП.
Первое, что приходит на ум, - начать поддерживать два многоключевых файла СОТРУДНИКИ и ОТДЕЛЫ: первый файл должен содержать поля СОТР_ИМЯ, СОТР_НОМЕР, СОТР_СТАТ, СОТР_ЗАРП и СОТР_ОТД_НОМЕР, а второй - ОТД_НОМЕР, ОТД_РУК, СОТР_ЗАРП (общий размер зарплаты) и ОТД_РАЗМЕР (общее число сотрудников в отделе). Тогда большая часть неудобств, перечисленных в предыдущем абзаце, будет преодолена. Каждый из файлов будет содержать только недублируемую информацию, необходимость в динамических вычислениях сводной информации не возникнет. Но заметим, что после такого перехода информационная система будет обладать некоторыми новыми возможностями, сближающими ее с СУБД.
Прежде всего, теперь система должна знать, что она работает с двумя информационно связанными файлами (это шаг в сторону схемы базы данных), ей должны быть известны структура и смысл каждого поля (например, что СОТР_ОТД _НОМЕР в файле СОТРУДНИКИ и ОТД_НОМЕР в файле ОТДЕЛЫ означают одно и то же), а также понимать, что в ряде случаев изменение информации в одном файле должно вызывать модификацию второго файла, чтобы общее содержимое файлов было согласованным. Например, если на работу принимается новый сотрудник, то необходимо добавить запись в файл СОТРУДНИКИ, а также соответствующим образом изменить поля ОТД_ЗАРП и ОТД_РАЗМЕР в записи файла ОТДЕЛЫ, описывающей отдел этого сотрудника.
Вообще, согласованность данных является ключевым понятием баз данных. На самом деле, если информационная система (даже такая простая, как в нашем примере) поддерживает согласованное хранение информации в нескольких файлах, можно говорить о том, что она поддерживает базу данных. Если же некоторая вспомогательная система управления данными позволяет работать с несколькими файлами, обеспечивая их согласованность, можно назвать ее системой управления базами данных. Уже только требование поддержания согласованности данных в нескольких файлах не позволяет обойтись библиотекой функций: такая система должна обладать некоторыми собственными данными (мета-данными) и даже знаниями, определяющими целостность данных.
Но это еще не все, что обычно требуют от СУБД. Во-первых, даже в нашем примере неудобно реализовывать такие запросы, как "выдать общую численность отдела, в котором работает Иван Арутюнович
Шепитько". Было бы гораздо проще, если бы СУБД позволяла сформулировать такой запрос на близком пользователям языке. Такие языки называются языками запросов к базам данных. Например, на языке SQL наш запрос можно было выразить в форме
SELECT ОТД_РАЗМЕР FROM СОТРУДНИКИ, ОТДЕЛЫ WHERE СОТР_ИМЯ = "ИВАН АРУТЮНОВИЧ ШЕПИТЬКО" AND СОТР_ОТД_НОМЕР = ОТД_НОМЕР
При формулировании запроса СУБД позволит не задумываться о том, каким образом будет выполняться этот запрос. Среди ее метаданных будет содержаться информация о том, что поле СОТР_ИМЯ является ключевым для файла СОТРУДНИКИ, а ОТД_НОМЕР - для файла ОТДЕЛЫ, и система сама воспользуется этим. Если же возникнет потребность в получении списка сотрудников, не соответствующих занимаемой должности, то достаточно предъявить системе запрос
SELECT СОТР_ИМЯ, СОТР_НОМЕР FROM СОТРУДНИКИ WHERE СОТР_СТАТ = "НЕТ",
и система сама выполнит необходимый полный просмотр файла СОТРУДНИКИ, поскольку поле СОТР_СТАТ не является ключевым.
Далее, представим себе, что в первоначальной реализации информационной системы, основанной на использовании библиотек расширенных методов доступа к файлам, обрабатывается операция регистрации нового сотрудника. Следуя требованиям согласованного изменения файлов, информационная система вставила новую запись в файл СОТРУДНИКИ и собралась модифицировать запись файла ОТДЕЛЫ, но именно в этот момент произошло аварийное выключение электрического питания. Очевидно, что после перезапуска системы ее база данных будет находиться в рассогласованном состоянии. Потребуется выяснить это (а для этого нужно явно проверить соответствие информации с файлах СОТРУДНИКИ и ОТДЕЛЫ) и привести информацию в согласованное состояние. Настоящие СУБД берут такую работу на себя. Прикладная система обязана знать, какое состояние данных является корректным, но всю техническую работу принимает на себя СУБД.
Наконец, представим себе, что мы хотим обеспечить параллельную (например, многотерминальную) работу с базой данных сотрудников. Если опираться только на использование файлов, то для обеспечения корректности изменений на все время модификации любого из двух файлов доступ других пользователей к этому файлу будет блокирован (вспомните возможности файловых систем для синхронизации параллельного доступа). Таким образом, зачисление на работу Петра Ивановича Сидорова существенно затормозит получение информации о сотруднике Иване Сидоровиче Петрове, даже если они будут работать в разных отделах. Настоящие СУБД обеспечивают гораздо более тонкую синхронизацию параллельного доступа к данным.
Таким образом, СУБД решают множество проблем, которые затруднительно или вообще невозможно решить при использовании файловых систем. При этом существуют приложения, для которых вполне достаточно файлов, приложения, для которых необходимо решать, какой уровень работы с данными во внешней памяти для них требуется, и приложения, для которых безусловно нужны базы данных.
Современные системы управления файлами и управления базами данных представляют собой весьма совершенные инструменты, каждый из которых может быть очень успешно применен в соответствующей области деятельности. Но всегда необходимо помнить, что каждый инструмент приносит максимальную пользу именно в той области, для которой он создан.