Firebird, zeos, multithreading
Модератор: Модераторы
- Brainenjii
- энтузиаст
- Сообщения: 1351
- Зарегистрирован: 10.05.2007 00:04:46
Firebird, zeos, multithreading
Добрый день,
жажду организовать работу с Firebird из многопоточного приложения, как это правильно сделать?
Сейчас мне представляется это следующим образом - на каждый поток создаётся по экземпляру TZConnection, TZQuery и TZReadOnlyQuery. Из TZReadOnlyQuery читаю несмотря ни на что, а Update/Insert/Delete оборачиваю в TZConnection.StartTransaction+CommitTransaction. Возможно придётся создавать 2 TZConnection - для TZQuery и TZReadOnlyQuery (если CommitTransaction закрывает TZReadOnlyQuery).
Несколько беспокоит, что TZConnection.Connect выполняется около секунды - UIB по воспоминаниям сравлялась с этим гораздо быстрее (да и раньше я держал одно соединение на все потоки, что неправильно, как понимаю).
В общем, буду очень рад советам - как правильно организовать работу с Firebird в многопоточном приложении, используя Zeos (или предложения по другим библиотекам, поддерживающим x86_64).
Спасибо.
жажду организовать работу с Firebird из многопоточного приложения, как это правильно сделать?
Сейчас мне представляется это следующим образом - на каждый поток создаётся по экземпляру TZConnection, TZQuery и TZReadOnlyQuery. Из TZReadOnlyQuery читаю несмотря ни на что, а Update/Insert/Delete оборачиваю в TZConnection.StartTransaction+CommitTransaction. Возможно придётся создавать 2 TZConnection - для TZQuery и TZReadOnlyQuery (если CommitTransaction закрывает TZReadOnlyQuery).
Несколько беспокоит, что TZConnection.Connect выполняется около секунды - UIB по воспоминаниям сравлялась с этим гораздо быстрее (да и раньше я держал одно соединение на все потоки, что неправильно, как понимаю).
В общем, буду очень рад советам - как правильно организовать работу с Firebird в многопоточном приложении, используя Zeos (или предложения по другим библиотекам, поддерживающим x86_64).
Спасибо.
Brainenjii
Вас беспокоит только долгое соединение TZConnection?
Я, обычно, создаю по одному соединению на каждое, не связанное между собой, действие. Время соединения мне, при этом, ни сколько не мешало. Правда у меня не было ситуаций, когда изменение данных надо было проводить как-то уж очень быстро.
Если параметр времени критичен, то можно заранее создать некое предопределённое количество потоков с постоянно открытыми соединениями, но их не должно быть сильно много.
Вас беспокоит только долгое соединение TZConnection?
Я, обычно, создаю по одному соединению на каждое, не связанное между собой, действие. Время соединения мне, при этом, ни сколько не мешало. Правда у меня не было ситуаций, когда изменение данных надо было проводить как-то уж очень быстро.
Если параметр времени критичен, то можно заранее создать некое предопределённое количество потоков с постоянно открытыми соединениями, но их не должно быть сильно много.
- Brainenjii
- энтузиаст
- Сообщения: 1351
- Зарегистрирован: 10.05.2007 00:04:46
Нашёл что общим решением при работе с БД в многопоточных приложениях является Connection Pool - создание нескольких постоянно открытых подключений с менеджером доступа к ним. В общем-то всё довольно легко, остался только вопрос - как быть с read-only транзакциями? На каком этапе можно сказать, что соединение, использованное под чтение уже не используется? После отработки Open(), достижения EOF, или после Close? В однопоточных приложениях с UIB я создавал одну читающую транзакцию (Read Commited) на весь период работы приложения и для чтения вызывал её - проблем не возникало.
TZConnection.InTransaction: Boolean;
- Brainenjii
- энтузиаст
- Сообщения: 1351
- Зарегистрирован: 10.05.2007 00:04:46
Спасибо. Наконец-то вернулся к ZEOS'у. Правда неудачно - не могу повторить "успех" с выгружением данных - как бы не бился - всё одно получаю Exception cо "Statement Is Not Allowed". ZEOS 6.6.6, птица 2.1
Brainenjii
А как Вы выгружаете?
И куда?
А как Вы выгружаете?
И куда?
- Brainenjii
- энтузиаст
- Сообщения: 1351
- Зарегистрирован: 10.05.2007 00:04:46
Вот тестовый пример:
В выводе получаю:
Код: Выделить всё
program Project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, ZConnection, ZDataset;
{ you can add units after this }
{$R *.res}
Var
aConnection: TZConnection;
aQuery: TZReadOnlyQuery;
begin
aConnection := TZConnection.Create(nil);
aConnection.HostName := 'localhost';
aConnection.Database := 'mybase';
aConnection.User := 'SYSDBA';
aConnection.Password := 'mypass';
aConnection.Protocol := 'firebird-2.1';
aConnection.ReadOnly := TRUE;
aConnection.Connect;
aQuery := TZReadOnlyQuery.Create(nil);
aQuery.Connection := aConnection;
aQuery.Connection.StartTransaction;
aQuery.SQL.Text := 'SELECT * FROM MY_TABLE';
aQuery.Open;
While Not(EOF) Do
Begin
WriteLn(aQuery.FieldByName('MYFIELD).AsString);
aQuery.Next;
End;
aConnection.Commit;
aQuery.Free;
aConnection.Disconnect;
aConnection.Free;
end.
В выводе получаю:
Brainenjii@blinux:~> /tmp/project1
An unhandled exception occurred at $00000000005A813C :
EZSQLException : Statement is not allowed
$00000000005A813C line 866 of ../../lazarus/components/zeos/src/dbc/ZDbcInterbase6Utils.pas
$00000000005B806A line 559 of ../../lazarus/components/zeos/src/dbc/ZDbcInterbase6Statement.pas
$00000000005B7C40 line 542 of ../../lazarus/components/zeos/src/dbc/ZDbcInterbase6Statement.pas
$000000000049D553 line 598 of ../../lazarus/components/zeos/src/dbc/ZDbcInterbase6.pas
$00000000006278C1 line 2211 of ../../lazarus/components/zeos/src/component/ZAbstractRODataset.pas
$0000000000626A17 line 1978 of ../../lazarus/components/zeos/src/component/ZAbstractRODataset.pas
$00000000004AD9C2
$00000000004B143E
У TZConnection есть свойство AutoCommit, по умолчанию =True.
Попробуйте установить его в False.
Попробуйте установить его в False.
- Brainenjii
- энтузиаст
- Сообщения: 1351
- Зарегистрирован: 10.05.2007 00:04:46
Бред какой-то. Устанавливаю AutoCommit в FALSE - не получается сделать ZConnection.StartTransaction - пишет, что AutoCommit установлен в FALSE - и шишь тебе, а не транзакция... Ставлю в TRUE - при проверке на ZConnection.InTransaction - выдаёт TRUE сразу после соединения... Кто-нибудь, покажите тестовый примерчик элементарного коннекта к БД и вытаскиванию из таблицы поля для консольного приложения (или приложите гуйовый) 
- Brainenjii
- энтузиаст
- Сообщения: 1351
- Зарегистрирован: 10.05.2007 00:04:46
Тогда ОЧЕНЬ буду рад решению для работы с Firebird на 64 битных системах
Код: Выделить всё
While Not(EOF) Do
Begin
WriteLn(aQuery.FieldByName('MYFIELD).AsString);
aQuery.Next;
End;Кстати, а к чему относится EOF?
- Little_Roo
- энтузиаст
- Сообщения: 639
- Зарегистрирован: 27.02.2009 18:56:36
- Откуда: Санкт-Петербург
svk12 писал(а):Код: Выделить всё
While Not(EOF) Do
Begin
WriteLn(aQuery.FieldByName('MYFIELD).AsString);
aQuery.Next;
End;
Кстати, а к чему относится EOF?
EOF - End Of Fil
А Вы вообще-то о чем спрашиваете ?
- Brainenjii
- энтузиаст
- Сообщения: 1351
- Зарегистрирован: 10.05.2007 00:04:46
Поторопился... Но суть не в этом - до EOF оно даже не доходит... В таком примере стопорится на Connect вообще... В реальном проекте - вышеописанная история с AutoCommit'ом и StartTransaction/InTransaction... Слов просто нет - обновил дома компьютер - и на тебе - не поработать толком... Есть на форуме хоть кто-нибудь, кто работает с Firebird'ом на 64 bit?
UPD: отставить истерику
Прописал от безысходности -dUseCThreads, снёс всё, поставил zeos-7.0.0-alpha - ЗАРАБОТАЛО!!! Жизнь продолжается, всем спасибо ^_^
UPD#2: поторопился радоваться... Теперь приложение валится с Runtime error: 216... Но уже лучше чем совсем ничего...
UPD: отставить истерику
UPD#2: поторопился радоваться... Теперь приложение валится с Runtime error: 216... Но уже лучше чем совсем ничего...
- Little_Roo
- энтузиаст
- Сообщения: 639
- Зарегистрирован: 27.02.2009 18:56:36
- Откуда: Санкт-Петербург
Brainenjii писал(а): снёс всё, поставил zeos-7.0.0-alpha - ЗАРАБОТАЛО!!! Жизнь продолжается, всем спасибо ^_^
Ну наконец-то, хоть кто-то не стал хвалить СТАБИЛЬНУЮ 6.6.6
У меня так же было - только на 32 бит (но это, видимо, фича) - компиляция происходила в течении 5-7 минут
Как только перешел на 7 версию (а потом, что и есть самое главное) - на версии из SVN - проблема ушла...
