Знакомство с СУБД Firebird
Денис "Denver" Мигачев, оригинал
Причины, по которым СУБД Firebird является достойным выбором для вашего следующего проекта.
В мире Open Source было сделано многое для создания функционально полноценной, гибкой и удобной в использовании системы управления базами данных - СУБД, которая смогла бы выдерживать большие нагрузки и еще иметь интерфейс доступа из популярных языков программирования, таких, как PHP и Perl. За долгое время развития систем хранения данных на этом рынке определились два сильнейших игрока, MySQL и PostgreSQL. Но постепенно в борьбу за право называться лучшей СУБД вступает третий игрок - СУБД Firebird. Сервер предлагает широкий набор функций, имеет отличный послужной список еще в бытность им СУБД InterBase. Как будет рассказано ниже, Firebird имеет внушительные возможности, доступные, как правило, только в коммерческих системах управления базами данных включая хранимые процедуры, триггеры, архивирование базы во время ее работы (hot backup - "горячая" архивация), репликацию и многое другое. Как и другие уже сложившиеся продукты, Firebird несет в себе наследство от своих предшественников, что может немного отпугнуть нового пользователя. Так что перед тем, как погрузиться в исследование особенностей, предоставляемых этим сервером баз данных, рассмотрим некоторые общие проблемы, которые могут возникнуть.
Сервер Firebird изначально начитал свою жизнь как продукт компании "Борланд" под названием InterBase. Когда была готова к выходу шестая версия этой СУБД, руководство "Борланд" решило, что разработка и дальнейшее развитие сервера нерационально, и выложило исходные коды на корпоративном портале под лицензией Open Source. Потом, однако, компания-производитель изменила свое решение, снова закрыла доступ к исходным кодам СУБД и чуть позже продолжила разработку. Отчасти, кстати, это было вызвано растущей популярностью Firebird. На сегодняшний день "Борланд" продолжает разработку InterBase с доступной на момент написания статьи версией 7.1. СУБД Firebird 1.0 являлась фактически исправленной версией InterBase 6.0 Open Edition. Поэтому первой полноценной, "чистой" версией Firebird можно считать версию 1.5.
Для не знакомого с сервером пользователя Firebird имеет две непривычных особенности. Первая - СУБД имеет две архитектуры, Сlassic и Super Server; вторая - наличие нескольких диалектов SQL, каждый из которых вносит свои особенности в работу. Рассмотрим сначала особенности архитектуры, а потом продвинемся к диалектам SQL и к тому, как они связаны с SQL Firebird.
Как уже говорилось, СУБД Firebird поставляется в двух вариантах, Classic Server и Super Server. Архитектура Classic Server может характеризоваться следующим образом: каждому клиенту по собственному серверу. Это означает, что в классической архитектуре для каждого из клиентских подключений создается серверный процесс, обслуживающий одного клиента. Процессом запуска управляет внешний процесс, например, inetd или xinetd для ОС Unix.
Архитектура Super Server была разработана как направление для развития и разработки сервера Firebird в будущем. Даже компания "Борланд" еще до опубликования исходных кодов решительно заявляла о скором отказе от Classic Server и переходе на Super Server. Суперсервер обрабатывает все клиентские запросы в нескольких потоках одновременно внутри одного серверного процесса, и такая схема работы требует совсем немного ресурсов при создании новых подключений. Использование системных ресурсов и управление блокировками намного более эффективно происходит в архитектуре Суперсервер, потому что раздельные потоки не нуждаются в ожидании завершения обработки других потоков ядром сервера - это все происходит внутри одного процесса. Но при работе с сервером архитектуры Суперсервер программист должен учитывать, что любые пользовательские функции включая внешние программы, работающие с базой данных под управлением Суперсервера, должны быть написаны очень аккуратно и быть как можно более защищенными от сбоев, так как нарушения в их работе могут повлечь падение самого сервера и (возможно) нарушение целостности данных. Для тех, кто знаком с архитектурой СУБД Oracle, может быть проще разобраться с обработкой подключений, если рассматривать архитектуру Classic как соответствующую выделенным подключениям, в то время как работа Super Server больше походит на систему совместного использования подключений.
Еще один аспект этой базы данных, который может несколько озадачить разработчика, - это наличие сразу трех диалектов SQL. Диалекты в большинстве своем различаются форматом хранения типов даты-времени, а также точностью численных типов данных. Здесь поможет хорошее правило: если вы не знаете всех особенностей диалектов Firebird, используйте третий диалект (dialect 3). Он не только наиболее соответствует последним стандартам ANSI SQL, но и будет легко понятен пользователям СУБД MySQL и Sybase. Диалект устанавливается как при подключении, так и во время исполнения программы или с помощью команды isql set sql dialect.
Установка СУБД Firebird. Так как разработчики расценивают архитектуру Super Server как платформу для будущего развития Firebird, при написании статьи все примеры выполнялись именно на этой архитектуре Super Server. На момент создания статьи СУБД Firebird версии 1.5 была доступна только в бинарном виде. К сожалению, разработчики не сопроводили пакет хоть малым документом по инсталляции (наверное, потому, что ставится она и правда очень просто), так что ниже приведены, правда, очень кратко, основные шаги по инсталляции и запуску Firebird под ОС Linux.
Чтобы установить сервер под ОС Linux, разверните архив (обычно это tar-файл) программами bunzip и tar в папку usr/local. При этом будет создана папка usr/local/firebird. Если вы хотите, чтобы сервер баз данных стартовал при загрузке системы, запустите на исполнение сценарий minitinstall.sh, находящийся в папке usr/local/firebird. В другом случае запустите файл firebird.initd:
# sh ./firebird.initd start
По умолчанию сервер баз данных прослушивает порт номер 3050. Если есть необходимость, его можно изменить в конфигурационном файле сервера и перезапустить сервер. Для установки, возможно, потребуется библиотека libstdc++5.so, которая поставляется вместе с glibc 3.2, поэтому надо проверить, есть ли она у вас. Также может потребоваться правка файла /etc/ld.so.conf - добавление строки /usr/local/firebird/lib и затем запуск ldconfig для того, чтобы операционная система могла производить поиск библиотек в этой директории. И, наконец, многие инструменты сторонних производителей (Perl, PHP, Python) также используют libgds.so для обработки клиентских подключений. Этого файла нет в поставке Super Server, однако проблему удается решить созданием ссылки на файл libfbclient.so, что, кажется, удовлетворяет запросы клиентских приложений. Бытует мнение (но мной не было проверено), что помогает простое переименование файла libfbclient.so в файл с названием libgds.so.
Подробнее об особенностях. Несомненно, очень важно ответить на вопросы, которые возникают вокруг других СУБД с открытым исходным кодом, особенно вокруг MySQL. Ответы на основные вопросы из них приведены ниже.
Поддерживаются ли транзакции? Транзакции полностью поддерживаются, они могут быть подтверждены (commit) либо отменены (rollback). Более того, сервер Firebird может работать с такими понятиями, как savepoints - точки сохранения, и может производить откат транзакций к точкам сохранения, что очень похоже на такой же механизм, существующий в СУБД Oracle. Применение точек сохранения полезно в том случае, если в хранимой процедуре или триггере необходим откат изменений к определенной логической точке. В СУБД Firebird и в триггере, и в хранимой процедуре есть возможность вернуться к какой-либо заранее определенной точке сохранения. Таким образом, если перед выполнением нескольких SQL-операций поставить точку сохранения, то в любой момент выполнения этих операций можно будет вернуться к состоянию, соответствующему состоянию на момент установки точки сохранения.
Есть ли поддержка внешних ключей? Сервер Firebird использует стандартный синтаксис SQL для определения внешних ключей в таблицах. К примеру, следующий текст создает внешний ключ для подчиненной таблицы:
SQL> create table parent (parent_id int not null primary key,
CON> parent_val varchar(10));
SQL> create table child (child_id int not null, parent_id
CON> int not null, child_val varchar(10),
CON> primary key (child_id),
CON> foreign key (parent_id) references parent(parent_id));
Поддерживается ли блокировка на уровне строк таблицы? По умолчанию Firebird использует мультиверсионную систему хранения данных. Это означает, что все сессии видят устаревшие данные до тех пор, пока новые версии этих данных не будут подтверждены. Альтернативный вариант техники включает в себя эксклюзивное блокирование с помощью команды SQL select … for update with lock. В обоих случаях уровень блокирования лежит на уровне записей. Следующий пример показывает работу многоверсионной системы хранения:
Сессия № 1:
SQL> select * from parent
PARENT_ID PARENT_VAL
============ ==========
1 Preimage
SQL> update parent set parent_val = 'Postimage' where parent_id = 1;
SQL> select * from parent;
PARENT_ID PARENT_VAL
============ ==========
1 Postimage
Сессия № 2:
SQL> select * from parent;
PARENT_ID PARENT_VAL
============ ==========
1 Preimage
Сессия №1:
SQL> commit;
Сессия №2:
SQL> commit;
SQL> select * from parent;
PARENT_ID PARENT_VAL
============ ==========
1 Postimage
Как можно видеть, неподтвержденные транзакции в сессии №1 не блокируют доступ к данным во второй сессии. Сессия №2, тем не менее, имеет доступ только к старой версии записи, но не к обновленной. Второй, не менее важный механизм блокирования, как уже было сказано выше, - select … for update with lock option. Так делать удобно в том случае, когда сессии необходимо иметь эксклюзивную блокировку записи; это гарантирует, что ни одна другая сессия не сможет изменить данные, пока сессия не снимет блокировку. Таким образом считается, что данные не изменяются со времени выборки и до того момента, когда они обновляются.
Сессия №1:
SQL> select * from parent where parent_id = 1 for update with lock;
PARENT_ID PARENT_VAL
============ ==========
1 Postimage
Сессия №2:
SQL> update parent set parent_val = 'Postimage2' where parent_id = 1;
(Ошибка !)
Как видно из примера, сессия №2 не может обновить значения данных, пока сессия №1 не завершится подтверждением или откатом. Уровень блокировки такого уровня сложности недоступен в СУБД MySQL даже при использовании таблиц типа InnoDB.
Существует ли поддержка хранимых процедур и триггеров? В этой части Firebird блеснул перед своими конкурентами. Преимущество наличия стандартного языка хранимых процедур позволяет разработчикам не тратить время на получение специализированных знаний. Фактически для создания хранимых процедур и триггеров достаточно простого знания SQL. Процесс создания хранимых процедур очень прост, и вот тому подтверждение:
SET TERM !! ;
CREATE PROCEDURE insert_into_child (os_type varchar(10))
AS BEGIN
insert into child (child_id, parent_id, child_val) values (gen_id(gen_child_id, 1),
(select parent_id from parent where parent_val='os'), :os_type);
if (:os_type = 'linux') then begin
insert into child (child_id, parent_id, child_val) values (gen_id(gen_child_id, 1), (select parent_id from parent where parent_val='os'), 'LinuxRocks'); end
else begin
insert into child (child_id, parent_id, child_val) values (gen_id(gen_child_id, 1), (select parent_id from parent where parent_val='os'), 'Boo!'); end
EXIT;
END !!
SET TERM ; !!
А вот пример триггера, проверяющего вставку и обновление в дочерней таблице в зависимости от значения поля в этой таблице:
SET TERM !! ;
CREATE trigger you_said_it for child after insert or update
AS BEGIN
if (new.child_val = 'LinuxRocks') then insert into child (child_id, parent_id, child_val) values (gen_id(gen_child_id, 1), (select parent_id from parent where parent_val='os'), 'YouSaidIt!'); EXIT;
END !!
SET TERM ; !!
Репликация. Многие средства репликации созданы сторонними разработчиками. Большинство из них основываются на механизме триггеров, отслеживающем вставки, обновления или удаления в таблицах базы, и затем применяют их в другой базе данных. Насколько мне известно, все эти решения являются коммерческими по своей сути (хочешь больше защиты - плати деньги) и предназначены для администрирования баз данных на различных платформах включая Windows и Linux/Unix.
Несколько файлов одной базы данных. Вообще говоря, по умолчанию сервер Firebird создает базу данных в одном файле с расширением FDB. Однако в последующем возможно разбиение данных по нескольким файлам с указанием количества страниц для дополнительных файлов. Хотя практически в этом нет необходимости, за исключением случаев, когда размер файла базы данных приближается к предельному размеру, определенному для операционной системы. Если есть возможность держать разные файлы базы данных на разных дисках, это исключит возможные проблемы с заполнением дискового пространства. В отдельных файлах можно размещать даже таблицы.
Выводы. Некоторые могут удивиться, зачем они должны тратить время и силы, стараться осваивать новую СУБД, особенно если они уже знакомы с СУБД MySQL или PostgreSQL. С моей точки зрения Firebird предлагает удобный путь миграции от коммерческих СУБД с закрытым исходным кодом к продуктам Open Source, в то же время предлагая разработчику намного больше свободы в создании приложений. Я нахожу процедуру перехода от Oracle к MySQL или PostgreSQL немного сложной и трудоемкой, так как по природе эти серверы слишком отличаются от своих коммерческих собратьев. Firebird же позволяет сделать переход на новую СУБД легче и быстрее. Если читатель уже знаком с любой из популярных СУБД, знания, полученные за годы работы, могут быть полезны и для работы с Firebird. Эта СУБД имеет практически все черты, характерные лучшим серверам баз данных без нанесения сколько-нибудь значительного вреда производительности, что подтверждают многочисленные промышленные тесты. И если вы ищете СУБД для вашего следующего проекта, подумайте о Firebird - он этого достоин.