То есть, если на данном компьютере ведется разработка попеременно для одного и другого сервера, то лучше серверы НЕ запускать как сервис, а запускать как приложение (ibserver.exe -a, fbserver.exe -a). Создайте 2 bat или cmd файла, в которых пропишите вызовы instreg и запуск сервера как приложения. Помните о том, что обращение сервером к "чужой" БД может также вызвать проблемы (см. выше). По крайней мере, вы будете видеть по иконке в таскбаре, какой именно сервер в данный момент работает на вашей машине. И не забудьте в конфигурации обоих серверов прописать одинаковые параметры, если вы сравниваете серверы по производительности или другим характеристикам.
После установки Firebird перестали работать кодировки
Скорее всего вы поставили не все файлы Firebird – дело в том, что в FB в районе билда 400 нашли ошибку, которая не позволяла в бесплатных версиях Interbase 6 и Firebird создавать собственные кодировки при помощи CollateKit. Исправление этой ошибки привело к несовместимости нового ibserver.exe со старыми gdsintl. Поэтому при установке новых версий Firebird (или файлов из архивов snapshot) нужно обновлять все файлы dll, exe (или соответствующие для unix), а не только ibserver.exe. Это же правило относится и к Yaffil.
После установки Yaffil стал падать сервер или udf
Yaffil начиная со сборки 867 компилируется MSVC7. Это означает, что теперь используется сервисная библиотека msvcr7.dll, а не msvcrt.dll как раньше (msvc6). В этой библиотеке есть функция malloc, отвечающая за аллокирование памяти.
Таким образом, если ваши udf содержат фунции с free_it, которые напрямую аллокируют память вызовом функции из msvcrt, или наоборот, делают это правильно через ib_util.dll но от сервера IB или FB, в результате получается что ваша udf использует один менеджер памяти, а сервер – другой. Что и приводит ко всяким проблемам с работоспособностью сервера.
Убедитесь, что ваша функция использует вызов не malloc, а ib_util_malloc, и что ib_util.dll имеет версию Yaffil не ниже 865 сборки (а также что на компьютере нет других ib_util.dll, которые могут быть найдены операционной системой ранее правильной ib_util.dll).
Не могу подсоединиться к серверу
Начнем с того, что надо убедиться, что сервер запущен и работает. При этом на сервере не должно быть FireWall-ов или прокси, которые не дают ему слушать порт 3050 по tcp/ip (или firewall/прокси надо настроить, чтобы не мешали Interbase). По WinXP SP2 (Firewall блокирует порт 3050) см. тут.
База данных должна находиться на сервере или компьютере, где установлен InterBase или Firebird, обычный или Desktop, Embedded, Personal и т. п.), и не должна быть "расшарена". InterBase, Firebird и Yaffil являются СУБД с клиент-серверным доступом к БД, то есть к файлу базы данных обращается только сервер, и ни в коем случае не клиентская часть или приложение (даже в случае embedded).
После этого надо убедиться, что если у вас в сети нет серверов Netware, то ни один клиент или сервер не имеет установленной поддержки протоколов IPX/SPX (NWLink и т. п). Этот протокол только мешает работе.
Далее, проверьте видимость сервера с клиента простым ping. Однако, не всегда если ping работает, это означает что с настройками сети все в порядке.
В общем, если операционные системы установлены корректно, и сеть правильно настроена, то InterBase и Firebird должны тоже работать нормально. По поводу настройки сети обращайтесь к документации на используемые операционные системы.
Если используется локальный коннект к БД, то причиной невозможности подсоединения к серверу может быть: некорректная gds32.dll (от другого сервера), или конкретная gds32.dll не поддерживает локальный коннект вообще (см. далее пункт "Ошибка unavailable database"); сервер запущен как сервис. В этих случаях нужно просто использовать протокол доступа tcp, например localhost:c:\dir\data.gdb. Путь к базе – диск и каталог – всегда являются "локальными" для сервера. То есть, диск c:, d: и т. п. – это логический диск, существующий на том же компьютере, где установлен InterBase или Firebird. Использовать mapped drive или subst недопустимо.
На Windows с IB/FB можно работать по NetBeui и по TCP. На Unix – только по TCP. Лучше всего netbeui не использовать, т. к. этот протокол требует выдачи прав на доступ к каталогам и файлам баз данных на сервере, чего делать категорически не рекомендуется.
Часто путают протоколы коннекта
Netbeui - \\srv\c:\dir\data.gdb
причем это вовсе не означает, что каталог c:\dir на сервере srv должен быть "расшарен".
TCP/IP – srv:c:\dir\data.gdb
(разделители \ и / можно использовать как угодно и вперемешку. Сервер сам разберется. srv – это имя или ip-адрес компьютера, на котором установлен IB/FB).
Для всех версий InterBase (кроме Yaffil и Firebird) есть правило – если поддержка протокола tcp/ip в операционной системе установлена после установки сервера или клиента IB, то в файл services (без расширения) надо добавить строку
gds_db 3050/tcp
и после нее сделать перевод строки (пустую строку). После чего, если это сделано на сервере, сервер IB надо перезапустить.
Примечание. Если речь идет о "локальном коннекте", и об
ошибке Unavailable database – у вас или клиентская часть от другого сервера, или сервер работает как сервис, и поэтому не обязан поддерживать локальный коннект. Используйте доступ по протоколу tcp.
Не работает или перестал работать Classic (CS)
Скорее всего речь идет о Windows. Причем, если Classic перестал работать или не работает, то SuperServer может работать.
Причиной проблемы является установка на сервере программы, которая перехватывает соединения tcp, и "не дает" главному процессу Classic запускать новые процессы перенаправляя на них новые коннекты пользователей. К такому ПО относятся как серверные так и клиентские части разнообразных proxy – WinProxy, MS Proxy, WinGate и т. п., некоторые антивирусы (совершенно однозначно NOD32), или другое подобное ПО.
В случае появления проблемы необходимо указать такому ПО в его настройках, чтобы fb_inet_server.exe (или ibremote.exe для Yaffil) не "обрабатывался".
Ошибка Unavailable database
Вы пытаетесь подсоединиться к БД через "локальный протокол" (см. пункт выше) – c:\dir\data.gdb. Вместо этого нужно использовать сетевой протокол, например, localhost:c:\dir\data.gdb. Причиной ошибки может быть:
- Вы пытаетесь использовать локальный протокол (см. выше) на Windows Vista или Windows 7. Работать через локальный протокол под этой ОС будут только
- InterBase 2007 SP1 и выше
- Firebird 1.5/2.x с установленным параметром IpcName=Global\FIREBIRD в firebird.conf
- причем, если запуск IB/FB идет как приложения, а не как сервиса, то также наверняка потребуется запуск не из обычной консоли, а из консоли с административными правами.
- Клиентская часть (gds32.dll, fbclient.dll) не соответствует версии сервера. Локальный протокол может быть несовместим даже между минорными (Firebird 1.5.0, 1.5.1, InterBase 7.0, 7.5) версиями одного и того же сервера.
- Клиентская часть не поддерживает локальный протокол вообще. Такое бывает. Например, в Firebird 1.5.1 for Windows, Classic.
- Сервер запущен как сервис. В этом случае локальный протокол, реализуемый через shared memory (есть еще реализация xnet) просто "не виден" между клиентом и сервером. Иногда такое работает, но в случае если и клиент запускается из под сервиса (IIS и т. п.) – не работает точно. Также локальный протокол не работает если на Win2003 или WinXP запущены службы Terminal Services.
Локальный протокол совершенно точно не работает под Windows Vista, если соединение идет от приложения к IB/FB как к сервису. Если IB/FB запущен как приложение, то локальный протокол работает, но примерно на 20% медленнее чем под Windows XP.
- Особенности конкретного логина или версии операционной системы. Бывают случаи, когда локальный протокол не работает, даже если сервер запущен как приложение, и клиентская библиотека точно соответствует версии сервера. Это выглядит как "на одной машине работает, а на другой - нет".
Во всех случаях проблем с локальным протоколом рекомендуется проверить все вышеперечисленные варианты проблем, и если их не удалось устранить – использовать локальный сетевой протокол для соединения с БД (localhost:c:\dir\data.gdb).
Еще одной причиной unavailable database может быть указание несуществующего диска в пути к БД. В этом случае данное сообщение будет выдано также и для сетевого соединения.
Не берется база с расшаренного диска
И не должна. Файл базы данных должен находиться на том же компьютере, что и сервер IB/FB/YA. Причем строка подключения должна содержать диск и путь к базе данных в именах локальных для этого сервера дисков (c:, d:, e: и так далее).
Теоретически файл БД можно положить на другой компьютер, если организовать том Networking File System (чаще встречается на unix). Однако это может привести к нестабильной работе и безусловной порче данных в случае обрыва соединения между компьютером с БД и компьютером с IB/FB/YA. Кроме того, при связи например в 100 мегабит сервер будет очень медленно работать с БД (сравните скорость обмена данными по сети со скоростью доступа к IDE HDD).
Не удается сделать больше 10, 60, 70, 150 подключений
Проверьте в настройках сервиса IB – должна стоять галочка в "Allow service to interact with Desktop". Если галочка установлена, но проблема остается, значит дело не в IB, а в настройках операционной системы или приложений, которые контролируют доступ по tcp/ip к серверу.
Ограничивающими число коннектов на Windows могут быть также антивирусы (nod32 и т. п.) или разнообразные proxy-клиенты или серверы.
На Linux следует проверить конфигурацию inetd/xinetd, там тоже может быть ограничение в 60 (или более) подключений.
Как найти сервер InterBase, Firebird, Yaffil в сети?
Никак. Собственно, вам это может понадобиться только если вы хакер.
Interbase во время работы "слушает" порт 3050, но, например, при заходе на этот порт телнетом никак себя не проявляет. Порт вместо 3050 может быть любым другим, если в services он указан иначе для gds_db.
При отключении клиентов остаются коннекты на сервере. После некоторого времени отключаются клиенты
Сначала проверьте, нет ли на вашем сервере прокси или firewal. Если да – в первую очередь проверьте их настройки по отключению неактивных коннектов, если таковые настройки есть. Если proxy, firewall и т. п. на сервере нет (включая как серверную часть, так и клиентскую часть proxy, например), то можно прочитать статью www.ibase.ru/devinfo/keepalive/
Для Windows можно посмотреть и изменить настройки tcp:
http://support.microsoft.com/default.aspx?kbid=140325
http://support.microsoft.com/default.aspx?kbid=120642 (см. настройку KeepAliveTime)
Для Linux – то же самое, т. е. конфигурирование tcp.
Что такое UDF и где их взять?
UDF – это пользовательские функции, находящиеся в разделяемых библиотеках (dll, so), которые можно использовать при выполнении запросов на сервере. Есть ряд библиотек готовых функций, в том числе с исходными текстами, а также можно писать UDF самостоятельно.
Если вы пишете UDF на Delphi, то портировать эти функции под Linux можно при помощи среды разработки Kylix. Функции на C/C++ можно скомпилировать любым подходящим компилятором (MSVC, Borland C++, GNU ...).
По написанию UDF есть хорошая статья и масса примеров включая готовые библиотеки UDF. Используйте примеры или готовые библиотеки функций в качестве "болванок", если вам нужна своя функция.
Самые большие наборы функций – FreeUDFLib, RFunc.
Не могу подключить UDF
На этот вопрос есть несколько ответов:
- В IB 6 изменились правила подключения UDF – теперь подключаемые библиотеки должны лежать только в подкаталоге udf установленного сервера. Это сделано для обеспечения безопасности. Кроме того, в Firebird введен параметр ibconfig
EXTERNAL_FUNCTION_DIRECTORY
при помощи которого можно указать несколько дополнительных каталогов для хранения UDF.
- Есть еще сообщения о том, что UDF, компилируемые Delphi 6 Update Pack 2 "не видны" сервером под WinNT 4.0. При этом якобы проблему можно устранить установкой SP6 на WinNT.
- Нужно убедиться, что имя функции экспортируется из dll в точном соответствии с тем, которое указано в declare external function. На некоторых операционных системах могут быть проблемы с регистрочувствительностью экспортируемых из dll функций.
- Базовая библиотека (или другие) ib_udf.dll зависит от библиотеки ib_util.dll. Соответственно, зависимую библиотеку загружает не сервер, а именно оригинальная dll. Поэтому правила загрузки подчиняются правилам, действующим например для Windows для функции Win32 – LoadLibrary. А это значит что ib_udf.dll должна находиться в системном пути или в общем пути переменной PATH (для embedded допускается в текущем каталоге).
Как правильно аллокировать память для UDF с FREE_IT?
Нужно делать следующим образом – начиная с InterBase 5.0 в комплект сервера входит ib_util.dll содержащая функцию ib_util_malloc. Ее объявления для C и Pascal есть в каталоге include:
ib_util.h - extern void * ib_util_malloc (long);
ib_util.pas - function ib_util_malloc(l: integer): pointer; cdecl; external 'ib_util.dll';
Для аллокирования памяти и FREE_IT нужно использовать эту функцию. Поскольку сервер сам освобождает занятый участок памяти, функция для освобождения памяти в этой библиотеке не предусмотрена.
При этом ib_util.dll должна находиться в PATH или рядом с вашей dll UDF. Позаботьтесь о том, чтобы на сервере не было двух или более ib_util.dll от разных серверов. В противном случае возможна некорректная работа сервера, его падение или что еще хуже – повреждение базы данных.
Причиной такой несовместимости может быть то, что сервер (ibserver.exe, fbserver.exe и т. п.) для Windows компилируется определенной версией MSVC (5, 6, 7), использующей свою версию менеджера памяти. Соответственно, аллокировать в UDF память надо функцией этого же менеджера. На сегодняшний момент есть msvcrt.dll, msvcr60, msvcr70, msvcr71, поэтому игнорировать ib_util.dll и принудительно указывать malloc как функцию из msvcrt нельзя.
Использование ib_util является 100% переносимым, т. к. эта библиотека является стандартной для Interbase (всех версий выше 5.0), Firebird и Yaffil и поставляется под все платформы.
Если вы сами аллокируете/деаллокируете память внутри UDF (с FREE_IT или без), то можете для этих целей использовать любые функции, в том числе getmem/freemem в Delphi.
Как правильно объявлять функции UDF – stdcall или cdecl?
Правильно – cdecl, как на C так и на Pascal (Delphi). Например,
function Add_A(var iSmall: SmallInt; var iLong: Integer): Integer; cdecl; export;
begin
Result := iSmall + iLong;
end;
В документации по InterBase вплоть до версии 7.0 ошибочно указана необходимость использования stdcall. Документация в этом плане исправлена только в InterBase 7.1.
Что такое IBX?
IBX – это набор компонент для Delphi и C++Builder, позволяющий работать с серверами IB 4.x, 5.x, 6.x напрямую. Поддерживает диалекты 1-3 для IB 6. Содержит компоненты Services API IB6, позволяющие управлять серверами IB, их параметрами, делать удаленный backup/restore, проверять базы данных и др.
IBX "унаследован" от FreeIBComponents (FIBC), но кроме общих черт содержит массу design-time редакторов свойств, упрощающих выбор типов транзакций, параметров подсоединения, запросов и т. п.
Описание компонент IBX с примерами использования.
Самое последнее обновление IBX x.08 находится на codecentral.borland.com. Также можно взять исходные тексты IBX с sourceforge.net/projects/ibx, но обновляются они достаточно редко.
Services API IBX работает только с серверами архитектуры SuperServer. Services API в серверах архитектуры Classic поддерживается только в Yaffil Classic и Firebird 1.5.1 Classic.
Почему не обновляются данные?
Как правило это означает, что вы работаете с компонентами прямого доступа, и не настроили свойства компонента IBTransaction. Этот компонент по умолчанию не содержит параметров транзакции, а такие транзакции в InterBase API имеют уровень изолированности SNAPSHOT. Т. е. транзакция не может видеть чужих committed изменений. Вам нужно сделать двойной щелчок мышью на компоненте, и выбрать тип транзакции read committed.
Подробнее по транзакциям см. документ.
Как выполнять запросы параллельно в приложении или как работать с IB/FB из threads?
Начиная с IB 4.2 клиентская часть InterBase поддерживает параллельное выполнение операций в разных коннектах (соответственно, клиентские части Firebird и Yaffil обеспечивают ту же функциональность, ни больше ни меньше). Т. е. для того чтобы работать параллельно из приложения, надо в каждом thread приложения (там где это нужно) открыть свое соединение (TIBDatabase для IBX, для BDE см. пример BKQUERY в поставке Delphi и C++Builder).
Кроме того, желательно открытие коннекта (IBDatabase.Connected:=True) выполнять монопольно, т. е. в отсутствие других параллельно выполняющихся операций.
Пример работы с thread в IBX: ibx_mt.zip, ibxthreads.zip.
Для параллельной работы во всех версиях InterBase, и в Firebird до 2.0, существует еще одно требование – коннект к БД не должен быть локальным. В Firebird 2.0 и выше локальный протокол изменен, и допускает параллельное выполнение запросов из разны коннектов.
Внимание! В вышеуказанных примерах ошибочно используется подключение к БД через локальный коннект, что приведет к невозможности параллельной работы из threads на InterBase и Firebird до версии 2.0.
Также, при одновременном вызове функции подсоединения к БД (isc_attach_database) из разных threads может возникнуть ошибка. Открывайте БД "последовательно" (еще лучше isc_attach_database производить в главном thread).
Клиентская библиотека Firebird 2.5 является потокобезопасной (thread-safe), что означает лишь то, что при одновременном вызове двух функций API из разных тредов одна из функций будет ожидать завершения другой. Параллельного выполнения функций в пределах одного коннекта вы не получите.
Где взять ODBC для 6.0?
ODBC-драйверы для 6.0 появляются как грибы после дождя. См. ссылки на ODBC в IB6.
Русские буквы с InterClient
С разрешения Сергея Астахова, владельца страницы http://people.comita.spb.ru/users/sergeya/java/ruschars.html#db, приводится часть раздела, описывающая работу с русскими буквами в InterClient:
InterBase (interbase.interclient.Driver)
Для этого драйвера работает параметр "charSet":
// Параметры соединения с базой
Properties connInfo = new Properties();
connInfo.put("user", username);
connInfo.put("password", password);
connInfo.put("charSet", "Cp1251");
// Устанавливаем соединение
Connection db = DriverManager.getConnection(dataurl, connInfo);
Однако не забудьте при создании БД и таблиц указать кодировку символов. Для русского языка можно использовать значения "UNICODE_FSS" или "WIN1251" (см. О работе с русскими буквами в InterBase/Firebird).
В версии 2.01 InterClient присутствует ошибка – классы ресурсов с сообщениями для русского языка там неправильно скомпилированы. Скорей всего разработчики просто забыли указать кодировку исходников при компиляции. Есть два пути исправления этой ошибки:
- Использовать interclient-core.jar вместо interclient.jar. При этом русских ресурсов просто не будет, и автоматом подхватятся английские.
- Перекомпилировать файлы в нормальный Unicode. Разбор class-файлов – дело неблагодарное, поэтому лучше воспользоваться JAD-ом. К сожалению JAD, если встречает символы из набора ISO-8859-1, выводит их в 8-ричной кодировке, так что воспользоваться стандартным перекодировщиком native2ascii не удастся – придётся написать свой (программа Decode). Если Вам не хочется заморачиваться с этими проблемами – можете просто взять готовый файл с ресурсами (пропатченый jar с драйвером – interclient.jar, отдельные классы ресурсов – interclient-rus.jar).
Но даже настроив JDBC-драйвер на нужную кодировку, в некоторых случаях можно нарваться на неприятности. Например, при попытке использования новых замечательных скролируемых курсоров стандарта JDBC 2 в мосте JDBC-ODBC из JDK 1.3.x довольно быстро можно обнаружить, что русские буквы там просто не работают (метод updateString()).
Поддерживает ли BDE третий диалект (IB 6 и выше)?
Да. Вот кусочек из readme.txt от Delphi 6 (туда входит BDE 5.2)
Для работы в диалекте 3 необходимо добавить в registry в ветке
HKEY_LOCAL_MACHINE\SOFTWARE\
Borland\Database Engine\Settings
\Drivers\Intrbase\Db Open\
строку (string) SQLDIALECT и установить ее значение в "3" (без кавычек).
Эта настройка действует только для вновь создаваемых алиасов BDE, т. е. существующие алиасы надо ПЕРЕСОЗДАТЬ.
Для работы с серверами 5.6 необходимо установить значение этого параметра в алиасе BDE в 1.
Внимание! Однако, даже такая настройка не даст полноценной работы из BDE с базами данных в третьем диалекте. Типы DATE/TIME/TIMESTAMP будут обрабатываться нормально, однако, например, тип NUMERIC(18,2), хранимый во внутреннем представлении INT64, будет восприниматься как неизвестный тип столбца, т. е. TBytesField. Понятно, что с числами через такой тип TField работать невозможно. Поэтому, для работы в третьем диалекте вам придется использовать dbExpress, IBX, FIBPlus, IBObjects и другие наборы компонент.
Как указать роль (ROLE) в BDE?
ROLE поддерживаются начиная с BDE 5.01, однако был момент когда существовало несколько версий 5.01. Поэтому лучше всего использовать версии BDE выше, чем 5.01 (версию можно узнать посмотрев properties/version файла idapi32.dll).
Причем параметр ROLE NAME будет виден только для новых алиасов, а не для старых. Т.е. для появления новых параметров нужно пересоздать алиас. Если при этом параметр роли не появился, то следует взять файл sql_int.zip, распаковать его, и в BDE Administrator подключить этот файл через меню Object/Merge Configuration. После этого вновь создаваемые алиасы будут иметь параметры ROLE NAME для указания роли, WAIT ON LOCK для указания параметров транзакций wait/nowait (см. статью по транзакциям), и COMMIT RETAINING для явных транзакций (см. статью по транзакциям).
В Login Dialog параметр роли все равно выводиться не будет, поэтому нужно создавать свой собственный диалог логина для TDatabase.
Чем можно работать с IB 6?
Если база данных в диалекте 1, то к ней можно обращаться из программ, поддерживающих IB4 или IB5. Если БД перенесена в диалект 3 (или создана в нем), то пока вариантов немного:
- IBConsole. Не очень удобный инструмент. Не рекомендуется делать им backup/restore в бете IB 6 и в релизе IB 6 (IBConsole build 308 и 309). IBConsole есть как для Windows, так и для Linux.
- IB_SQL. Поддерживает 6.0, диалекты 1 и 3.
- Другие, намного более удобные инструменты третьих фирм, см. раздел http://www.ibase.ru/download/.
Не могу открыть базы данных от 4/5.x из 6.0, или unsupported on-disk structure for x.gdb;found 9(8), support 10
Сообщение гласит о том, что используемая версия IB не поддерживает базы данных старого формата (от 5.x). Для работы надо в 5.x сделать backup базе данных, и restore в 6.0. Или использовать другой билд (например FireBird), который поддерживает старый формат баз данных.
Основная проблема в том, что 6.0 поддерживает новую версию BLR (Binary Language Representation, формат скомпилированных процедур и триггеров), которая несовместима с использовавшейся в 5.x. В результате поддержка старых баз данных то появлялась, то пропадала. Например, бета-версия IB 6 не поддерживала формат ODS9. Также не поддерживают старые базы билд Borland InterBase 6.0.1 от 10 января 2000 (версий 6.0.1 было несколько). Наоборот, все версии FireBird поддерживают старые базы данных, и также обещают подобную поддержку в сертифицированных билдах Borland InterBase. См. FAQLINK от Borland.
Под какие платформы выпускается InterBase, Firebird, Yaffil?
Приведен список версий серверов, операционных систем, и какой вариант сервера выбрать для двух и более процессорных систем.
По поводу использования HyperThreading см. документ www.ibase.ru/devinfo/ht/
Для каждой операционной системы версия сервера может быть Classic и/или SuperServer. Например, Yaffil и FB 1.5 есть и Classic и SuperServer, Firebird 1.0 for Windows – только SuperServer, Firebird for FreeBSD – только Classic, InterBase 6.5 и выше для любой платформы – только SuperServer, и т. д.
В столбце "2 и более процессоров":
-
"нет" – не рекомендуется, или имеет смысл привязать процесс сервера к одному процессору (например, для Windows через утилиту ibaffinityLINK или через параметр CPU_AFFINITY в ibconfig/firebird.conf).
-
"да" – этот вариант сервера под данной операционной системой будет использовать все процессоры. Для IB 7.x требуется приобретение процессорных лицензийLINK на каждый +1 физический процессор.
Для облегчения выбора "да" выделено жирным шрифтом.
Сервер |
Тип сервера |
Операционная система |
2 и более процессоров |
InterBase 6.0 |
SuperServer |
Windows |
нет |
Linux |
нет |
Solaris-SPARC |
нет |
Classic |
Linux |
да |
InterBase 6.5 |
SuperServer |
Windows |
нет |
Linux |
нет |
Solaris-SPARC |
нет |
InterBase 7.x |
SuperServer |
Windows |
да |
Linux |
да |
Solaris-SPARC |
да |
Firebird 1.0 |
SuperServer |
Windows |
нет |
Linux |
нет |
Solaris-x86 |
нет |
HP-UX |
нет |
Classic |
Linux |
да |
Solaris-x86 |
да |
Solaris-SPARC |
да |
FreeBSD |
да |
MacOS/X |
да |
HP-UX |
да |
Firebird 1.5 |
SuperServer |
Windows |
нет |
Linux |
нет |
Classic |
Windows |
да |
Linux |
да |
FreeBSD |
да |
MacOS/X |
да |
sinixz |
да |
Solaris-x86 |
да |
Yaffil |
SuperServer |
Windows |
нет |
Classic |
Windows |
да |
Имена файлов дистрибутивов InterBase и Firebird могут содержать буквы cs (Classic) и ss (SuperServer). Дистрибутив Firebird 1.5 for Windows содержит в себе установку как Classic, так и SuperServer.
Для регулирования количества используемых сервером процессоров (только для Windows, SuperServer) существует параметр ibconfig CPU_AFFINITY (битовая маска).
Под Linux как правило имеется в виду Red Hat Linux. Допускается использование других вариантов этой ОС, с требованиями по минимальной версии kernel и glibc: например, для InterBase 7.x – kernel 2.2 and 2.4. Обратите внимание что от версии ядра Linux также зависит поддержка размеров одного файла БД более 4 гигабайт.
Под Windows имеются в виду Windows 98, ME, 2000, 2003, XP. На Windows 2003/XP не рекомендуется использовать старые версии – IB 6, FB 1.0.
В чем разница между архитектурами SuperServer и Classic?
Если в двух словах, то Classic создает процесс для каждого пользовательского коннекта, а SuperServer – один процесс, который обрабатывает запросы клиентов в разных threads (этого же процесса). Архитектура Classic надежнее, но требует больше памяти, т. к. кэш данных и метаданных у каждого процесса (пользователя) свой. SuperServer – производительнее, и имеет общий кэш данных и метаданных, но не распараллеливает запросы разных пользователей на многопроцессорных машинах. Распараллеливаемый SuperServer выпущен только Borland в версии Interbase 7.
Подробнее см. документ.
В Windows архитектура SuperServer была введена с версии 4.2. С тех пор (1995 год) версия Classic для Windows не выпускается. Для Linux (Unix) большинство портов были Classic, однако порт SuperServer также существует. Firebird выпускается, как правило, для всех вариантов Unix как в архитектуре Classic, так и SuperServer.
Borland в версии 6.5 прекратил выпуск Classic для всех платоформ.
Для Windows есть Classic – Yaffil и Firebird 1.5.
Borland Interbase 7 имеет архитектуру SuperServer, нормально распараллеливаемую на несколько процессоров (см. документLINK).
"Can not attach to password database" после установки
Данный вопрос касается только бета-версий IB 6 и самого последнего релиза IB 6.01 от Borland. FireBird может работать с БД от 5.x.
Скорее всего вы поставили IB 6 в каталог, где ранее был установлен IB 5 или 4. При установке инсталлятор не переписывает базу данных паролей пользователей (isc4.gdb), т.е. он ее сохраняет, предполагая что вы могли забыть сделать резервную копию этой БД. А поскольку бета IB6 не может работать с базами данных предыдущего формата (только после backup/restore), то и не может подсоединиться к isc4.gdb для получения пароля SYSDBA (или любого другого пользователя).
Если вам нужен isc4.gdb, то скопируйте его в isc4copy.gdb и положите в сторонку. Потом возьмите isc4.gdb из дистрибутива IB 6, и поместите на место старого. После этого подсоединиться можно как SYSDBA и masterkey. Для восстановления списка пользователей необходимо сделать backup isc4copy.gdb на IB версии 5, затем восстановить этот backup под IB6, остановить сервер IB6 и переименовать isc4copy.gdb в isc4.gdb.
Можно обойтись и без такой процедуры, если откопировать данные из старой базы данных в новый isc4.gdb каким-нибудь инструментом вроде datapump (см. Tools DownloadsLINK).
Select DISTINCT выполняется медленно или не использует индексы
В IB 6.0 оптимизатор использует сортировку (PLAN SORT) вместо использования индекса, как это было в 5.x.
Что такое "сертифицированные билды"?
"Сертифицированные билды" – означает дистрибутивы Interbase/Firebird, тщательно протестированные на определенной версии какой либо ОС (Windows, Linux, Solaris и т.д.). Причем как правило сертифицированные билды являются ПЛАТНЫМИ (см., например, faqLINK по сертифицированным билдам от Borland). Конечно, в любом случае в лицензии написано, что не дается никаких гарантий, однако такие версии работают намного более надежно, чем просто скомпилированные и выложенные на web.
Dpb constant 0 unknown
Это ошибка одной из самых древних версий IBConsole. У Вас однозначно слишком старый дистрибутив Interbase, а возможно даже и бета-версия 1999 года. Немедленно удалите эту версию с диска, и возьмите более свежую версию InterbaseLINK или FirebirdLINK. Еще лучше в качестве средства разработки использовать IBExpert.
Клиент от Firebird, Yaffil и IB7 не работает под Win95/98
Первая причина: во всех последних версиях IB в клиентской и серверной части используется только WinSock2 (например в Firebird начиная с билда 682). Windows 95 в этом плане уже устарела (в базовом комплекте есть только WinSock1), ей требуется обновление: http://www.microsoft.com/windows/downloads/bin/W95ws2setup.exe
Yaffil начиная с билда 860 не требует Winsock2 (достаточно winsock1).
Вторая причина: пока относится только к Yaffil – он скомпилирован MSVC7, поэтому в качестве сервисной библиотеки требуется msvcr7.dll, которая присутствует по умолчанию пока только в WinXP и Win2003 (Interbase и Firebird пока компилируются MSVC6, который требует msvcrt.dll. В чистой Win95 эта библиотека также отсутствует).
Поэтому для нормальной работы нужно положить msvcr7.dll (есть в дистрибутиве Yaffil) в path или рядом с gds32.dll.
Третья причина: Firebird 1.5 кроме обычно требуемой msvcrt.dll требует наличия msvcp60.dll. Этой библиотеки по умолчанию нет ни в Win95, ни в Win98.
Также см. пункт "После установки Yaffil стал падать сервер или udf".
Есть ли InterBase 6 или Firebird для Novell Netware?
Нет и не будет. Вообще данная операционная система плохо предназначена для работы в качестве сервера и в настоящее время является достаточно экзотической. Даже существовавшие версии Interbase (5.6, 4.2) для Netware не рекомендуется использовать по этим же причинам. Подробнее см. http://www.ibase.ru/devinfo/0108.htmLINK
DBD: ошибка Not enough LongReadLen buffer
Прислал Alex Maximenko:
Из справки по DBI: нужно устанавливать для $dbh аттрибут LongReadLen, который заведомо больше любого читаемого блоба. Это можно сделать как при коннекте к базе, так и на лету: $dbh->{LongReadLen} = ... / В принципе установка LongReadLen вроде лишнюю память не отнимает, так что установить этот параметр можно в DBI::connect.
Почему не используются два (четыре) процессора?
Начнем с того, что существует две архитектуры IB/FB – SuperServer и Classic. Вначале IB был только Classic, и первым SuperServer-ом стала версия 4.2 для Windows. Далее Classic оставался на Unix, а на Windows остался только SuperServer (см. выше о Classic в Firebird и Yaffil).
Различие Classic и SuperServer состоит в том, что Classic – старая технология, когда на каждого пользователя (коннект) создается процесс. Кэш БД у каждого процесса раздельный, и занимает он минимум 3 мегабайта памяти (в реальной жизни в среднем 10-20 мегабайт, бывает и 35). Поэтому в Classic при большом количестве пользователей требуется большое количество RAM.
SuperServer – это один процесс, где пользователи обрабатываются в threads (несколько пользователей могут обрабатываться одним thread-ом). В данном случае кэш БД общий, поэтому много пользователей не требуют много памяти.
Однако в случае падений сервера, если в Classic "погибает" только один пользовательский процесс, SuperServer "падает" весь.
При выпуске 6.0 Borland хотел отказаться от выпуска Classic, поэтому Services API в Classic фактически не реализовано. В 6.5 Classic вообще отсутствует, есть только SuperServer для Windows, Linux и Solaris. Однако, Firebird выпускает почти для всех ОС как Classic, так и SuperServer, и даже есть ОС на которых существует только Classic (FreeBSD). Более того, в настоящее время есть Yaffil Classic for Windows и Firebird Classic for Windows.
SuperServer не может использовать несколько процессоров в силу своей архитектуры. Конечно, загружены будут оба процессора, но из-за нераспараллеливания операций ввода-вывода каждый процессор будет загружен не более чем на 50% (при двух. При четырех – на 25%). Для решения этой проблемы в Firebird и позже в Interbase 6.5 был добавлен параметр IBCONFIG – CPU_AFFINITY. Это битовая маска, в которой указываются номера процессоров, которые необходимо задействовать. Например, 1 означает работу на первом процессоре, 2 – на втором, 3 – на первых двух и так далее. Освободившийся процессор можно занять другими задачами.
Самое оптимальное решение масштабирования при работе на многопроцессорных машинах – использование архитектуры Classic для Linux (или других Unix).
Хочу шифровать трафик
IB, FB или Yaffil не поддерживают шифрование трафика. Если вы хотите этого, то имеет смысл воспользоваться, например,
При более серьезных требованиях, например, сертификации средств шифрования, следует обратить взгляд на аппаратно-программные средства, например, http://www.ancud.ru/.
Скорее всего, никакие средства шифрования трафика в IB/FB/Yaffil в ближайшее время встроены не будут.
Медленный коннект (и работа) на WinMe/WinXP
Причина в том, что Me и XP содержат так называемую систему восстановления файлов. В соответствии со списком расширений любой файл, который изменяется, копируется системой в специальное место для возможного восстановления в дальнейшем. В этом списке есть расширение gdb, что приводит для IB к долгому коннекту и очень медленной работе.
Данную особенность можно выключить целиком:
- На XP: System Properties | System Restore | Turn off System Restore on all drives.
- Либо убрать из списка расширение gdb, отредактировав файл
на XP: $WINNT$\system32\Restore\filelist.xml
на Me: ... (примерно аналогичный, точное имя данного файла на ME не указано)
Или просто-напросто изменить расширение файла базы данных, на такой, для которого указанная функциональность не работает (например, для баз InterBase начиная с 7.0 рекомендуется расширение *.ib, только по указанной выше причине).
Примечание. Не нужно при этом упрекать MS в нелюбви к IB. Это просто случайность, т. к. расширения файлов в большинстве состоят из трех букв, количество комбинаций которых ограничено.
Медленный (долгий) коннект на Win2003
Это происходит только на старых версиях IB/FB/YA, например Interbase 6, Firebird 1.0.x. Причина – изменения в ядре Win2003, в результате чего ошибки синхронизации в коде старых версий IB/FB/YA стали проявляться в виде очень долгого коннекта (20 секунд и более), и иногда в виде нестабильной или очень медленной работы.
Избавиться от этой проблемы можно либо переходом на InterBase 7.1, Firebird 1.5, последнюю версию Yaffil, или возвратом на Windows 2000.
Нет коннекта после установки SP2 на Windows XP
После установки SP2 на Windows XP автоматически включается встроенный Firewall, который блокирует доступ практически по всем портам tcp/ip, и что самое главное – по порту 3050, который используют InterBase, Firebird и Yaffil для работы (по умолчанию). Т. е. порт 3050 в Firewall нужно открыть (если не будет работать, нужно еще открыть порт 113).
Если используются Events, то в Firebird 1.5 можно принудительно указать их работу по порту 3060 (например) параметром remoteauxport в firebird.conf. В случае остальных серверов, возможно, придется отключить firewall, или промониторить попытки открытия портов (утилитами с www.sysinternals.com), т.к. в предыдущих версиях для Events использовался произвольный номер порта tcp.
См. http://www.ixbt.com/soft/win-xp-sp2.shtml#Network_protection и http://edn.embarcadero.com/article/32532.
При выполнении запроса выдается "I/O Error for file..."
При выполнении запроса (скорее всего запрос содержит ORDER BY и план такого запроса содержит PLAN SORT) выдается ошибка:
"I/O Error for file c:\windows\temp\ib_sort_a02472.
Error while trying to write to file. Sort Error."
Имя файла может быть любым.
Это означает, что на диске, указанном в пути TEMP в системе нет свободного места для сортировки данных, возвращаемых запросом. Нужно или изменить переменную TEMP, чтобы она указывала на диск с достаточным свободным пространством, или сконфигурировать tmp_directory в ibconfigLINK (или firebird.conf).
При долгой работе переполняется память сервера
Выглядит это как увеличение памяти, потребляемой процессом сервера с течением времени, неосвобождение памяти при отключении всех пользователей, либо сообщение ОС о том, что виртуальная память кончилась и т. п.
Как правило, на 99% причина такой проблемы – это некорректно написанная UDF. Причем необязательно ваша, а, например, сторонняя (rfunc рекомендуется брать самой последней версии).
Лучше всего проверять UDF на утечки памяти при помощи процедур. Для этого делается процедура
create procedure testudf
as
declare variable i int;
declare variable s <>;
begin
i=0;
while (:i < 1000000) do
begin
s=MyUdf();
i=:i + 1;
end
end
при выполнении которой вы смотрите в TaskManager. Если занимаемая сервером память с течением времени увеличивается, значит, в udf есть утечки памяти.
Не удается создать вторичный ключ (FK)
При
ALTER TABLE X ADD [constraint FK_X] FOREIGN KEY (ID) REFERENCES Y (ID);
выдается сообщение
"unsuccessful metadata update, STORE RDB$REF_CONSTRAINTS failed,
action cancelled by trigger (1) to preserve data integrity,
Name of Referential Constraint not defined in constraints table."
В IB 6.0 (например 6.0.0.627) не удается сделать FK, если у таблицы Y к этому моменту уже есть FK по ID от любой другой таблицы, или просто индекс по полю ID, название которого начинается с буквы меньше S. Либо нужно сменить версию (в Firebird RC2 такой ошибки нет, как ее нет и в IB 5.6), либо располагать создание FK отдельно, в порядке detail-master, после чего создавать индексы (если по этим полям они вообще нужны).
Я удалил SYSDBA. Что делать?
Пока что в IB/FB/Yaffil все пользователи хранятся в файле ISC4.GDB (IB7 – admin.ib, FB 1.5 – security.fdb). Это обычная база данных. В дальнейшем, возможно, какой-либо из серверов будет поддерживать пользователей прямо в базах данных, без необходимости ISC4.GDB, но пока это только в планах.
Следовательно, нужно сделать следующее:
- остановить сервер IB
- скопировать isc4.gdb, например, в isccopy.gdb
- взять isc4.gdb из того самого дистрибутива, версия которого установлена, подсунуть на место isc4.gdb
- запустить сервер IB, теперь логиниться сможет только SYSDBA с паролем masterkey
- подсоединиться к isccopy.gdb и, например, IBExpert-ом извлечь данные из таблицы users в скрипт
- применить скрипт к новой isc4.gdb
- не забыть сменить пароль masterkey у SYSDBA, продолжить работу.
Что такое rdb$db_key?
Это "номер записи". Для таблиц он имеет длину 8 байт (для view – 8 байт умножить на количество таблиц в запросе, если запрос содержит явный или неявный join), которые представлены в виде строки, содержащей двоичные значения. Поэтому в ряде инструментов запрос
select rdb$db_key, t.* from table t
будет возвращать "мусор" в первом столбце.
rdb$db_key можно использовать в качестве уникального идентификатора записи, так же как и ее поле первичного ключа. Однако rdb$db_key по ходу работы может меняться. Физически он представляет собой номер таблицы, номер страницы и смещение на запись (причем не на конкретную версию, а вообще на пакет версий этой записи, если они есть).
По использованию rdb$db_key можно почитать следующие документы:
Есть ли хостинг баз InterBase/Firebird/Yaffil?
Да, есть. В России:
За рубежом:
Как правильно задать SEGMENT SIZE для BLOB?
Задавать этот параметр вовсе не нужно. Фактически, это атавизм – используется только утилитой GPRE при обработке Embedded SQL.
При этом препроцессор Embedded SQL будет использовать объявленный segment size просто как буфер требуемой длины для чтения или записи блоба. Blob segment size = 80 байт по умолчанию, потому что в изначальной версии InterBase в блобах хранились строки, а в те древние времена длина строки была обычно ограничена числом символов, помещающихся на алфавитно-цифровой терминал.
Компоненты или драйверы практически всегда используют жестко заданный размер "сегмента". Например, в IBX (и FIBPlus) размер буфера для записи куска данных в blob определяется константой DefaultBlobSegmentSize (ibblob.pas), которая равна 16к. Если посмотреть код функции записи blob
procedure WriteBlob(hBlobHandle: PISC_BLOB_HANDLE; Buffer: PChar; BlobSize: Long);
то в коде видно, что если размер записываемых данных меньше чем размер буфера (16к), то в isc_put_segment указывается скорректированный размер буфера (переменная SegLen).
Сервер сохраняет blob следующим образом:
- Если размер данных, записываемых в blob, помещается на свободном месте рядом с оригинальной записью, которой принадлежит blob – blob записывается на это место (при этом возникает "фрагментированность" страниц данных блобами, что в некоторых случаях может ухудшить производительность при обработке только записей). Объем свободного места зависит от размера страницы и количества записей, уже размещенных на этой странице.
- Если свободного места на странице записей нет, то для blob выделяется отдельная страница или несколько, в зависимости от размера blob. Если после записи blob на такой странице осталось свободное место, то оно остается пустым и не будет занято другими blob.
Таким образом, как видите, о размере сегмента при объявлении blob не стоит беспокоиться, совершенно.
Как работать с BLOB?
Достаточно просто. Даже если вы указываете подтип блоба (sub_type), серверу все равно, что вы будете там хранить – текст, картинку или звук.
Например, сохранить содержимое столбца blob в файл можно таким образом:
В C# (.Net): http://firebirdsql.org/dotnetfirebird/blob-reading-example-csharp.html
В IBX:
procedure TForm1.Button1Click(Sender: TObject);
begin
IBDataSet1.FieldByName('BLB') as TBlobField).SaveToFile('c:\blob.bin');
...
end;
То же самое – и в FIBPlus, см. статью http://www.devrace.com/ru/fibplus/articles/2261.php.
Практически то же самое – при записи, причем делать это можно двумя вариантами.
1. Передача blob через параметр. Имеется в виду запрос вида insert into table (field1, field2, blbfield) values (:param1, :param2, :blb); :
IBQuery1.ParamByName('blb').asBlob:=blobvar;
asBlob принимает значение в виде простой строки (string). Действительно, строки в последних версиях Delphi (как минимум с Delphi 3) могут содержать любую, в т. ч. двоичную информацию. Поэтому значение параметру blob можно присваивать и как asString.
2. Изменение столбца "редактируемого" DataSet – запись blob из файла в столбец:
IBDataSet1.Edit;
(IBDataSet1.FieldByName('BLB') as TBlobField).LoadFromFile('c:\blob.bin');
IBDataSet1.Post;
В предыдущих версиях IBX (до 4.42 включительно) можно было работать с blob иначе. Например, запись в файл
procedure TForm1.Button1Click(Sender: TObject);
var B: TIBBlobStream;
begin
B:=IBDataSet1.CreateBlobStream(IBDataSet1.FieldByName('BLB') as TBlobField, bmRead);
B.SaveToFile('c:\blob.bin');
B.Free;
end;
и чтение из файла
IBDataSet1.Edit;
B:=IBDataSet1.CreateBlobStream(IBDataSet1.FieldByName('BLB') as TBlobField, bmWrite);
B.LoadFromFile('c:\blob.bin');
B.Free;
IBDataSet1.Post;
Обратите внимание, что метод B.Free вызывается перед вызовом IBDataSet1.Post (а не наоборот, как это приведено в некоторых старых примерах в интернете).
Также, вопреки документации, давно (по крайней мере в версии IB 4.0 и выше) можно спокойно передавать и принимать blob как параметры процедуры. Существует, однако, обязательное условие – поскольку blob это дисковая структура, записываемый blob должен быть сохранен в столбце таблицы (insert/update), а считываемый blob должен быть выбран из таблицы (хотя можно из из функции чтения blob, например, LoadBlobFromFile из UDFDEMO).
Для работы с blob на сервере можно использовать UDF, например, из FreeUDFLib.
Как поместить базу на CD?
Для размещения БД на read-only носитете в InterBase 6.0 введены специальные ключи у gbak и gfix. Подробно по работе с такими БД читайте документацию (Operations Guide, страница 111).
Итак, делаете backup, а затем restore с ключами
gbak -c db.gbk db.gdb -mode read_only -use_all_space
Ключ -mode read_only включает у БД режим " только чтение". Т. е. транзакции стартовать можно, но разницы между commit/rollback нет, нельзя делать insert/update/delete или менять значения генераторов функцией gen_id().
Ключ -use_all_space максимально заполнит страницы данных и индексов, в результате чего БД по объему будет меньше чем обычно.
Перевести БД в read-only режим и обратно без backup/restore можно утилитой gfix.
Как в параметр передать несколько значений (where id in (:param)?
Вообще то никак. В параметр передать можно только одно значение. Попытка передать строку со значениями, разделенными например ',' в параметр для числа (a id здесь число) будет обречено на провал, тем более что сервер и не догадывается, что ему пытаются в :param передать список, а не конкретное значение. Однако, решение данной проблемы возможно.
Ded рекомендует:
Вообще-то мой метод при работе с клиента прост – раз такой запрос не может быть параметрическим, то я и не использую параметры, а между close и open пересобираю текст запроса, вставляя в него требуемую строку :-) Вот если такое требуется внутри процедуры, где запрос не пересобрать (с появлением execute statement стало менее актуально, если этот запрос не внутри цикла, то можно и пересобрать), тогда делаю так. Собираю строку с параметрами вот в таком виде
'~12~23~267~675~'
и запрос пишу
Select тыры-пыры
From Table T
Where :ParamStr Containing '~'||T.ID||'~'
тильду в качестве разделителя списка выбрал потому, что этот символ имеет наименьшие шансы встретиться внутри ID если это строковое поле. Кстати, этот фокус порой выигрывает у IN по быстродействию.
После изменения вызывается старая процедура, или ALTER PROCEDURE не работает
Это стандартное поведение сервера, начиная с версии InterBase 5.5 (февраль 1999 года). Оно описано в документации, Data Definition Guide, раздел Altering and dropping procedures in use (страница 157).
До версии 5.5 модификация процедур и триггеров во время работы приводила к падениям сервера. Проблему было решено устранить путем запрета обновления кэша метаданных, если к изменяемой процедуре обращаются пользователи. Например,
- Пользователь USR вызвал процедуру GETSOMETHING
- Программист в это же время делает alter procedure GETSOMETHING
- Сервер при alter меняет текст процедуры и ее blr в RDB$PROCEDURES, но не перегружает ее в кэше метаданных, потому что с этой процедурой работает пользователю USR
- Пользователь USR опять вызывает процедуру – срабатывает старый вариант процедуры, находящийся в кэше метаданных.
- Пользователь USR отсоединяется.
- Пользователь USR подсоединяется, вызывает GETSOMETHING – при этом если никто больше с этой процедурой не работал, код процедуры заново загружается в кэш метаданных, и выполняется новый вариант процедуры, модифицированный программистом в пункте 2.
Таким образом, чтобы загружался новый вариант процедуры, нужно отсоединить всех пользователей, которые вызывали эту процедуру хотя бы один раз, и подсоединить снова.
При однопользовательской работе разработчика такое поведение незаметно, разве только если разработчик не подсоединится к одной и той же БД из разных программ как 2 разных пользователя.
Примечание. В classic кэш метаданных не обновляется. Для "обновления" процедур обязательно нужно переподсоединиться к серверу. Данное поведение не имеет ничего общего с версионностью метаданных таблиц, и не имеет ограничений на количество alter procedure/trigger.
Можно ли отменить insert в триггере?
Можно, путем вызова EXCEPTOIN в триггере. При этом все действия в триггере будут отменены (если не обрабатывать exception), и также будут отменены все действия триггеров, которые были выполнены до указанного триггера. После чего exception будет выдан в тот контекст, откуда вызывался insert. То есть, insert будет целиком отменен.
В before insert совсем отменить insert и не вызывать при этом exception нельзя. В after insert – можно, только путем удаления уже вставленной записи. Например,
create trigger A for X
active after insert
as
begin
if (...) then
exception noinsert;
when any do
delete from X
where id = new.id;
end
Как создать базу данных?
Это можно сделать в IBConsole, IBExpert, через IBDatabase.CreateDatabase, через IB API и так далее, главное только:
- обязательно указать полный путь к базе данных, например, c:\dir
- желательно указать протокол tcp, даже если сервер на этой же машине (localhost:c:\dir. см. пункт)
- желательно указать расширение файла БД, оно может быть любым, но расширение gdb вызовет проблемы под XP и W2003. Правильно будет, например, c:\dir\data.ib или c:\dir\data.fdb
- желательно указать размер страницы 4096 или 8192 байт (см. пункт)
- желательно указать диалект 3 (см. пункт)
- желательно указать DEFAULT CHARACTER SET WIN1251 (см. "О работе с русскими буквами в InterBase/Firebird")
Как делать backup (резервную копию)?
Очень просто. Backup – это изготовление резервной копии базы данных "на ходу". Выполнять можно при работающих пользователях, однако надо помнить, что сохранены в backup будут только те данные, которые существовали на момент старта backup. Делать backup (и restore) можно как через Services API (в IBConsole, IBExpert и других, или в Delphi в палитре компонент InterBase Admin), так и утилитами командной строки.
Например,
gbak -b localhost:c:\dir\db.gdb d:\db.gbk -user SYSDBA -pass masterkey
расширение файла backup значения не имеет. Не рекомендуется делать backup на тот же логический диск, где лежит база (если кончится место, и БД перестанет работать, и бэкап не сделается), а еще лучше делать backup на отдельный физический диск (с точки зрения производительности).
Быстрее всего backup можно получить, если выключить сборку мусора, которая работает по умолчанию:
gbak -b -g localhost:c:\dir\db.gdb d:\db.gbk -user SYSDBA -pass masterkey
Мусор никогда не попадает в backup. Речь просто идет о том, что backup по умолчанию читая записи пытается определить, если у записи есть версии, то нужны они или нет. Ключ -g отключает это поведение.
Еще лучше всегда добавлять ключ -v, который приводит к подробному выводу действий backup. В этом случае, если произойдет ошибка, будет видно, где именно она произошла. Вывод можно направить и в файл:
gbak -b -g localhost:c:\dir\db.gdb d:\db.gbk -user SYSDBA -pass masterkey -v -y bak-log.txt
Backup рекомендуется делать регулярно, и сохранять его в архив (лучший вариант – ежедневный backup с сохранением 7-ми последних копий).
Делать архив БД через простое копирование файла БД можно, только если к этой БД нет ни одного подключенного пользователя файл БД это файл произвольного доступа, а копирование операционная система выполняет последовательно. В результате вы на выходе получите испорченную "копию" файла БД.
Внимание! Не рекомендуется делать restore в файл оригинальной БД (ключ -r или -rep в Firebird 2.x). Всегда делайте restore только с ключом -c.
Если backup будет каким-либо образом поврежден, восстановить из него базу данных вряд ли удастся.
Даже на нынешних рабочих станциях backup базы данных размером 2 гигабайта идет около 15 минут (с ключом -g). Если у вас этот процесс происходит как минимум в 2-3 раза дольше, значит сервер загружен другими задачами, у вас медленный винчестер, или проблемы какого-то другого рода.
Более подробно можно прочитать
- описание параметров утилиты gbakLINK
- сравнение скорости backup 1LINK и 2LINK, сравнение скорости restoreLINK.
- что такое "сборка мусора"LINK
- что такое sweepLINK
- описание версионности в Firebird и InterBaseLINK
Проблемы с float и double precision
Под проблемами имеются в виду вопросы:
- вставляю одно число, а вижу другое,
- не работает сравнение,
- не хватает точности,
- вылазит погрешность,
- и многие другие.
Рекомендуется прочитать:
Последний документ описывает поведение numeric/decimal в третьем диалекте (без вещественных чисел).
Кроме того, существует баг с округлением вещественных чисел, исправленный только в FB 1.5.2 (описан на странице 8 Firebird 1.5.2 Release Notes).
Использование генераторов в триггерах
Если у вас возникает такой вопрос, значит вам надо прочитать статью www.ibase.ru/devinfo/generator.htmLINK
Вкратце решение "проблемы" – значение генератора надо сначала получить в клиентское приложение (например, select gen_id(genname, 1) from rdb$database), а затем использовать его как значение столбца первичного ключа таблицы (до DataSet.Post). При этом вы не "потеряете" вставленную запись, не будет проблем со вставкой записей detail после вставки master, и т. п.
В триггере можно оставить присвоение столбцу значения генератора, если значение столбца is null. (if (new.field is null) then new.field=gen_id(genname, 1)).
Guardian и Classic, или гвардеец и классик – не работает, меняет реестр, и т. п.
Guardian (или "гвардеец") появился в InterBase 4.2, который впервые был реализован в архитектуре SuperServer (один процесс на всех пользователей). Поскольку эта версия не была свободна от багов, и например "падала" при одновременном изменении данных и метаданных, потребовался механизм для автоматического рестарта сервера IB в случае его сбоя. На Windows 95, 98 понятие "сервисы" отсутствовало, а в Windows NT 4.0 в свойствах сервисов не было возможности рестартовать сервер при сбое.
Поэтому было создано приложение ibguard.exe, которое при старте запускало ibserver.exe, и при его падении перезапускало его.
Соответственно, Guardian на компьютерах с операционной системой Windows 2000, 2003, XP, Vista – не нужен совершенно, т. к. свойства сервисов (Панель управления, Администрирование, Службы. например, закладка "Восстановление") позволяют не только настроить перезапуск сервиса при его падении, но и указать действия при последующих падениях.
Для архитектуры Classic "гвардеец" не нужен, и более того, не может рестартовать процесс Classic, вот почему: Classic работает в режиме "процесс для пользователя". То есть, если подключилось 10 пользователей, то в памяти будет 11 процессов fb_inet_server.exe. При старте самый первый процесс fb_inet_server занимается только прослушиванием порта 3050, и запуском новых процессов fb_inet_server при подсоединении пользователей. Именно поэтому число процессов Classic всегда n_подключенных_пользователей+1.
Более того, первый процесс fb_inet_server фактически никогда не может "упасть", т. к. он осуществляет достаточно примитивные операции. Guardian, в свою очередь, понятия не имеет, какой из процессов fb_inet_server чем занимается.
Возможность установки Guardian при установке Firebird Classic является недочетом инсталлятора Firebird.
Также атавизмом является FB Server Manager в панели управления, и не рекомендуется к использованию.
Как установить сервер Interbase или Firebird вместе со своим приложением? Как сделать свой инсталлятор сервера?
Это сделать очень просто. Во-первых, есть Install FAQLINK, в котором в том числе расписаны файлы, необходимые для работы InterBase и Firebird. Во-вторых, есть старый Embedded Installation Guide, который описывает то же самое. В-третьих, существует сайт ibinstall.defined.net, на котором собраны инсталляционные скрипты для разных инсталляторов.
Ну и последнее. Если вы пользуетесь InnoSetup (отличный бесплатный инсталлятор), то можете взять готовый скрипт для Firebird 1.5LINK, и поменять его как угодно.
Сервер не загружен, все жутко тормозит
Если это точно не сборка мусораLINK, и IBAnalyst подтверждает это, то значит это проблемы с сетью.
Если сервер Windows, то нужно запустить PerfMon, и включить мониторинг
Performance Object: Network interface
Counters: Output Queue Length
Instances: выбрать сетевую карту, которая обслуживает сеть клиентов сервера
Если размер Queue доходит до 250-400 пакетов, то это совершенно точно означает проблемы с передачей пакетов с сервера клиентам. Причиной может быть: драйвер сетевой карты, сама сетевая карта, свитч/хаб.
Для других операционных систем следует проверить то же самое.
Можно ли заменить FK на триггеры, или проверка целостности на триггерах
Часто возникает вопрос, можно ли заменить Foregin Key триггерами. Тем более, что в ряде case-инструментов есть пункт "декларативная или "триггерная" ссылочная целостность", где в первом случае создаются обычные FK между таблицами, а во втором – FK эмулируются триггерами.
Общий ответ – нет. FK нельзя заменить триггерами, потому что FK работают вне контекста транзакций, а триггеры – только в той транзакции, которая инициировала их срабатывание. Пример от Ded:
Start Transaction 1
Start Transaction 2
Transaction 1 - Delete From Master
Master Trigger - Select From Detail Where ID_Master=old.ID
Нету, чудненько, можем удалять (и удаляем).
Transaction 2 - Insert Into Detail (ID, Deleted_Master_ID)
Detail Trigger - Select From Master Where ID=new.Master_ID
Есть, чудненько, можно вставить (и вставляем).
Commit в любой последовательности, в результате в таблице detail появилась запись, ссылающаяся на удаленную в таблице master запись. Чего никогда не может произойти в случае наличия обычного FK.
Если же Master – статичный справочник, то есть удаление записей в нем запрещено как класс, и первичный ключ ни в нём, ни в детали не меняется, то FK можно удалить, и оставить нужные проверки на триггерах (это рекомендуется делать только в том случае, когда индекс по конкретному FK сильно неуникальный, и его создание при restore серьезно замедляет процесс restore. См. Дополнительные вопросы и ответы в Справке к IBAnalyst).
Есть ли ограничения на длину запроса или ограничения на число запросов в процедуре, триггере?
Отвечает Vlad Horsun:
Есть ли ограничения на длину SQL-запроса от клиента?
64K
Есть ли ограничение на длину скомпилированного кода запроса (процедуры, триггера)?
64К
Какое количество запросов может быть в процедуре, триггере?
255
"Запросами" считается обращение к таблице (контекст). На данный момент число контекстов ограничено 255, хотя в некоторых предыдущих версиях IB/FB было ограничение числа контекстов в 128.
Как ограничить выводимое число записей или есть ли в InterBase и Firebird аналог limit, top и т. п.?
Да, есть.
Начиная с InterBase 6.5 эта и последующие версии InterBase поддерживают синтаксис ROWS.
SELECT * FROM TABLE
ORDER BY
[ROWS [TO ] [BY ] [PERCENT] [WITH TIES]
Подробнее см. документациюLINK.
Начиная с Firebird 1.0 эта и последующие версии Firebird поддерживают синтаксис first/skip
SELECT first x skip y * FROM TABLE
Подробнее см. Release Notes. В Firebird 2.0 также будет поддерживаться синтаксис ROWS, совместимый с InterBase.
Оба "ограничителя" количества записей ROWS и first/skip работают следующим образом:
- сервер выполняет запрос
- на этапе передачи данных клиенту сервер пропускает skip/to записей, и после выдачи first/rows записей выдает клиенту сигнал eof
то есть, в случае обработки записей на сервере (order by без индекса, group by без индекса, выборка из процедуры и т.п.) сервер все равно сначала выполнит запрос целиком, и только после этого выдаст клиентской части запрошенное число записей. В обоих случаях указание rows/to или first/skip не имеет смысла без ORDER BY ("первые" записи из несортированного набора будут совершенно случайными), хотя Firebird поддерживает возможность в подзапросах указывать first/skip.
Примеры. Выбрать 5 записей, пропустив 10 из таблицы employee, упорядоченной по фамилии сотрудников:
select first 5 skip 10 *
from employee
order by last_name
select * from employee
order by last_name
rows 5 to 10
Update set a=b, b=a теряет значение a
Да, во всех версиях InterBase и Firebird столбцы меняются в update по мере присвоения им значений, а не "потом".
Это не соответствует стандарту, и подлежит исправлению, но существует ряд приложений, который использует именно текущее поведение. Возможно, будет исправлено на стандартное поведение в будущих версиях Firebird.
Особенности работы UPDATE и DELETE с подзапросами в условии, или delete с first в подзапросе удаляет все записи
Пример запроса:
delete from table1
where id in (select first N id from table1)
Такой запрос приведет к удалению всех записей в таблице table. Проблема в том, что InterBase и Firebird в данном случае (для update и delete) выполняет подзапрос для каждой записи таблицы table1, а не наоборот.
По стандарту сервер сначала должен выполнить подзапрос, а потом выполнить delete/update. Исправление нынешнего поведения Firebird рассматривается разработчиками.
Зацикливание на insert into table1 select * from table1
Движок InterBase и Firebird действительно зациклится на такой конструкции, т. к. в данном случае select будет неатомарным, т. е. он будет "подчитывать" вставляемые записи, из-за чего превратится в бесконечный цикл. Прервать такой запрос можно
- в InterBase 4.x/5.x/6.0 и всех версиях Firebird (до 2.1) – только остановкой процесса сервера
- в InterBase 6.5 – прерыванием запроса с клиента (сложно)
- в InterBase 7.x/2007 – прекращением запроса в tmp$statements, или отключением соответствующего соединения в tmp$attachments
Исправить проблему можно или указанием условия where, чтобы select не читал вставляемые записи, или добавлением конструкции order by которая привела бы к сортировке select в памяти (PLAN SORT в плане запроса).