Использование Interbase на ОС Linux.
Константин Кузнецов, klkuznetsov@ns.palata.ru
В данном материале я попытаюсь кратко изложить опыт двулетнего использования
InterBase 4.0 на Linux. Основная цель данного материала развеять множество
легенд о данном продукте, часть из которых, как это не странно, распространяет
компания Interbase. При этом постараюсь излишне не вдаваться в подробности
инсталляции, администрирования и настройки Linux, не касающиеся InterBase.
По моему
опыту, данная версия IB, в присутствии libc.5.xx.so, устойчиво работает
на следующих версиях ОС:
Redhat 4.2 – 6.0
Mandrake – 5.2 – 6.0
Slakware 4.0
Использовались
ядра от 2.0.30 до 2.2.13. В данный момент я использую следующую конфигурацию:
Slakware 4.0 (libc.5.so), ядро 2.2.13.
При этом
естественно компилировать что-либо работающее с IB (например IBPerl)
можно только если весь Ваш Linux собран с libc5.
Прежде чем приступать к установке InterBase, необходимо изменить следующие установки в ядре, и пересобрать его:
В случае, преобладания запросов с маленьким количеством данных, пересылаемых от сервера к клиенту (практически всегда), для ускорения работы, следует отключит буферизацию сетевых обменов для InterBase. Для чего следует откомпилировать программку следующего содержания. Комментарии сохранены специально:
/* From - Sat Oct 31 17:46:17
1998
Path: forums.borland.com!not-for-mail
From: Andy Bakun <abakun@reac.com>
Newsgroups: interbase.public.linux
Subject: fix for NAGLE problem
without kernel recompile
Date: Thu, 29 Oct 1998 17:49:40
-0600
Organization: Another Netscape
Collabra Server User
The Nagle algorithm option forces
use of the TCP_NODELAY option on all network
connections, which is generally
NOT what you want, since it can effect the
network transfer rate of other
high bandwidth protocols (which is why I believe
it is commented out now in the
linux kernel source). At my site, I wrote the
following program and used it
as a wrapper in inetd.conf (see below for that
part)
set_TCP_NODELAY.c:
----------------------------------
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
void main(int argc, char *argv[])
{
int value = 1;
setsockopt(0, IPPROTO_TCP, TCP_NODELAY,
(char *)&value,sizeof(int));
setsockopt(1, IPPROTO_TCP, TCP_NODELAY,
(char *)&value,sizeof(int));
setsockopt(2, IPPROTO_TCP, TCP_NODELAY,
(char *)&value,sizeof(int));
execl(argv[1], NULL);
}
/*
----------------------------------
Compile with:
$ gcc set_TCP_NODELAY.c -o set_TCP_NODELAY
Copy the set_TCP_NODELAY executable
to some well known location (I used
/usr/local/bin).
Edit your inetd.conf file, find
the gds_db line. Change the sixth through the
last fields to read the following:
/usr/local/bin/set_TCP_NODELAY
gds_inet_server /usr/interbase/bin/gds_inet_server
You essentially want to have
inetd startup the set_TCP_NODELAY program, and give
it options to start up gds_inet_server.
You probably had something like the
following for the sixth through
last fields:
/usr/interbase/bin/gds_inet_server
gds_inet_server
Note the order change. Those
who want a full explaination of the argument order
should consult the man page
for inetd(8).
What this little program does
is set it's stdin, stdout, and stderr? streams to
not use the Nagle algorithm,
then execs the Interbase gds_inet_server program.
Note that this is EXACTLY the
same effect as compiling your kernel with No Nagle
enabled, but it only effects
the programs you use it on (for our purposes,
gds_inet_server, but set_TCP_NODELAY
can be used in general with programs
started from inetd that need
it).
I hope you Interbase programmer
guys include setting the TCP_NODELAY socket
option in a future release of
gds_inet_server, if it isn't in the plan already.
:)
Andy Bakun.
abakun@reac.com
j park wrote:
> I've read various posts about
those who have disabled their NAGLE algorithms
> for performance purposes.
For whatever reason, we don't seem to be able to
> find that option to try it
for ourselves; we're not stupid but maybe our
> eyesight is bad. We're running
a version of Red Hat Linux and the Linux
> version seems to be 2.0.30.
>
> We were also told by the hardware
vendor that distributes Linux on their
> machines that this is something
they haven't heard of since the 1.x versions
> (which seems to agree with
what I've seen) and that this option can be set
> per-process (instead of the
whole kernel).
>
> Any comments?
>
> - NAGLED
*/
Остается добавить лишь killall –HUP inetd.
Так же, для увеличения производительности,
полезно указать на клиенте параметр соединения CACHE=n > 75.
Что собственно подразумевается под этим, наверно ни кому не известно. Мне почему-то думается о прозрачной переносимости наработок программиста между IBM PC и кластерами Digital Alpha под Open VMS. Если, имеется ввиду, два писюка с разным числом процессоров, то и Linux и Classic IB масштабируются великолепно (или хорошо на ядрах старой серии 2.0.XX). Как проверить? Берем машину примерно 2xPPro-200-256RAM, базу достаточно большую, но меньше чем объем оперативки (чтобы винтами не шуршал), коннектимся, запускаем серьезный запрос (желательно чтобы секунд 30 шел), измеряем время выполнения, смотрим в top – gds_inet_server – 50% ресурсов процессоров, открываем два коннекта к базе, запускаем два таких же запроса одновременно, смотрим в top – gds_inet_server – 50% процессоров – две одинаковые строчки, измеряем время выполнения каждого запроса - не изменилось. Делаем вывод: масштабируемость - линейная. Это был второй миф. Данное утверждение также проверялось на четырехпроцессорном PC.
Если у Вас планируется использование
IB без долгих статистических запросов или с одним пользователем, есть постоянно
присутствующий на работе MS Certified Professional, то смело ставьте на
сервер WINDOWS.
Единственный серьезный глюк IB 4.0, обнаруженный за два года эксплуатации, - это следующий эффект: если пользователь выключил машину не отсоединившись от базы, его процесс gds_inet_server занимает все доступные ресурсы процессора и пишет в interbase.log – inet error 32 со скоростью ~10Мбайт/c. Данная проблема решилась просмотром состояния сетки и убийством процессов, у который сервис gds_db в состоянии CLOSE. Я запускаю следующий скрипт из-под crond каждые две минуты.
#!/bin/bash
#echo "netst";
#killall -HUP inetd;
netstat -p --tcp --ip 2>/dev/null|
grep gds_db|
grep "CLOSE "|
awk '{print $5 " " $6 " " gensub("/","
","gggggggg",$7)}'|
while read host state pid proc
do
echo "Abnormally closed IB connections.
Killing";
echo HOST: $host " "STATE: $state
" " PID: $pid " "PROC: $proc;
kill -TERM $pid ;
killall -HUP inetd;
done
exit 0;
А также ln –sf /dev/console /usr/interbase/interbase.log.
Весьма удачной, на мой взгляд, является связка: Apache + perl + Ibperl = CGI, я думаю, в такой архитектуре, вполне можно построить приличную трехзвенку. Perl + IBPerl также очень удобен для перекачки, экспорта и импорта данных.
Привожу пример программы разбирающей и закачивающей в базы файлы формата CLF.
#!/usr/bin/perl
use IBPerl;
use strict;
print "Eating Apache log file...\n";
my $db = new IBPerl::Connection(
Server=>'altair',
Path=>'/bases/hit.gdb',
User=>'sysdba',
Password=>'****');
if ($db->{'Handle'}<0)
{
print "Connect error\n $db->{'Error'}\n";
};
my $count = 0;
my $tr = new IBPerl::Transaction(
Database => $db );
if ($tr->{'Handle'}<0)
{
print "Transaction error\n $tr->{'Error'}\n";
};
my $query =<<SQL;
INSERT INTO APACHE_LOG (
AL_HOST,
AL_IDENT,
AL_AUTHUSER,
AL_DATE,
AL_METHOD,
AL_REQUEST,
AL_PROTO,
AL_STATUS,
AL_BYTES)
VALUES (
?,
?,
?,
?,
?,
?,
?,
?,
?)\;
SQL
# print "$query\n";
my $st = new IBPerl::Statement(
Transaction => $tr, Stmt => $query );
if ($st->{'Handle'}<0)
{
print "Statement error\n $st->{'Error'}\n";
};
while (<>)
{
# print "$_\n";
my (
$client,
$identuser,
$authuser,
$datetime,
$tz,
$method,
$url,
$proto,
$status,
$bytes) =
/^(\S+) (\S+) (\S+) \[(\S+)
(\S+)\] "(\S+) (.*?) (\S+)" (\S+) (\S+)$/ or { next};
if ($bytes =~ /-+/) {
$bytes='0'};
if ($bytes eq "") {
$bytes='0'};
if ($status =~ /-+/) {
$status='0'};
if ( $st->execute(
$client,
$identuser,
$authuser,
$datetime,
$method,
$url,
$proto,
$status,
$bytes
) ) {
print "Executing errot\n $st->{Error}\n";
print "$_\n";
print "In string \n $query\n";
print "LINE: $client $identuser
$authuser $datetime $method $url $proto $status $bytes ";
} ;
$count++;
};
$st->close;
if ($tr->commit) {
print "Commit error\n $tr->{Error}
\n "};
print "Total processed $count
lines\n\n";
$db->disconnect;
exit 0;
С наилучшими пожеланиями Константин Кузнецов.
С автором можно связаться по адресу klkuznetsov@ns.palata.ru
Сегодня получил по рассылке ссылку на IB40LinuxHOWTO. Эксплуатирую эту систему около 2 лет. Хочу поделиться опытом насчет IB4Linux - в основном, это касается компиляции клиентских программ на платформах с glibc2 (сие потребовалось при переходе с RedHat 4.2 на 6.1). Условие сборки и, вроде бы, нормальной работы клиентов: - статическая компоновка с libgds.a - должен быть прилинкован модуль примерно следующего содержания
/* Make IB4 compatible with glibc */
#include <sys/stat.h>
#include <setjmp.h>
int _xstat(int ver,const char *filename, struct stat *statbuf) { return __xstat(ver,filename,statbuf);
}
int _fxstat(int ver,const int fildes, struct stat *statbuf) { return __xstat(ver,fildes,statbuf);
}
int __setjmp(jmp_buf env) { return setjmp(env); }
/* End of compat section */
ЭТО ПРОХОДИТ ТОЛЬКО ДЛЯ IB4!
PS. Еще недавно столкнулся с проблемой обработки дат на системах с compat-glibc - запрос select cast("now" as date) from rdb$database всегда выдает время GMT а не локальное. Оказалось, надо сделать mkdir /usr/lib/zoneinfo cd /usr/lib/zoneinfo ln -s localtime /etc/localtime Видимо, это баг compat-glibc.
Владимир Гончаров, vova@rpb.ru:
Я не тонкий знаток Interbase 4.0, но хотел бы добавить (по памяти - в последний раз эту процедуру я дел больше года назад):
- следует заменить суидные программы $INTERBASE/bin от пользователя root на аналогичные от ibase. То есть, преположим, что gsec имеет атрибуты
rwsr-xr-x 1 root root gsec
тогда
chown ibase gsec chmod +s gsec
поможет проблеме безопасности. Насколько я помню, возможность некорректного обращения к локальным файлам посредством программ от Interbase существовала(?) и при локальных вызовах.
- проблему interbase.log можно решить радикальнее-
ln -s /dev/null $INTERBASE/interbase.log
но у меня не было причин изучать его содержимое. Также, эта проблема появилась
то ли с 2.1.47, то ли с 2.1.6x. То есть ядра, 2.0.x этой болезни не подвержены
- я бы не стал изменять параметры ядра (по крайней мере, некоторые) посредством изменения ядерных исходников. Для этого есть /proc и аппарат sysctl, иначе необходимость срочной замены ядра (вследствии security flaw, например), может повлечь за собой серъезные проблемы (может не наложится очередной патч, к примеру)
- не совсем понятны рассуждения о масштабируемости. Приведенный пример ни о чем не говорит.
И в заключение, сервер Interbase 4.0 в моей организации стоит больше трех лет, закрывая довольно важное финансовое приложение на ядре 2.0.30. Максимальный uptime был больше года (UPS вскипел:(, но, правда, версия стоит немного другая Interbase for SCO под эмулятором iBCS. Переход на чисто Линуковую версию так и не состоялся про причине ненадобности - все и так работает :)
C уважением, Владимир Гончаров