Методы построения многопоточных приложений и немного проблем
Добавлено: 29 сен 2006, 15:02
Доброго времени суток!
Хотелось бы получить совет по нескольким вопросам.
Есть служба, написанная на Delphi 7. Работа с БД Firebird 1.5.2 в службе построена следующим образом:
Все изменения в БД производятся через ХП. Каждый поток (thread) владеет собственным IBDatabase и IBTransaction.
Вызов различных ХП прозводится следущим образом:
Выборка данных делается так:
Для транзакций используются следующие параметры
Проблема собственно в том, что через неопределенное количество дней возникает deadlock на запись в базу. Возникает несколько вопросов:
1. М.б. я имею где-то зависшую транзакцию (блокировку?). Как отловить, какая часть ПО берет в эксклюзивное пользование ресурсы БД?
2. Возможно у меня неверный подход к программной архитектуре. Какие возможны варианты построения служб, использующих Firebird - имеется ввиду использование БД в многопоточных приложениях. Точнее - какие грабли замечены?
3. При динамическом создании компонентов доступа к БД какие параметры устанавливать для БД, транзакции, запроса?
4. Если в потоке созданы IBDatabase и привязанная к нему транзакция, то нужно ли для создаваемого запроса создавать транзакцию или достаточно уже созданной? Практика показывает, что достаточно, но мало ли... (А для ХП получилось, что обязательно создавать транзакцию)
ИБ Аналиста ещё не запускал, попробую сегодня вечером.
Спасибо
Хотелось бы получить совет по нескольким вопросам.
Есть служба, написанная на Delphi 7. Работа с БД Firebird 1.5.2 в службе построена следующим образом:
Все изменения в БД производятся через ХП. Каждый поток (thread) владеет собственным IBDatabase и IBTransaction.
Вызов различных ХП прозводится следущим образом:
Код: Выделить всё
procedure TDBWriterThread.SetModemTypeId(Number:String;ModemTypeId:Integer;
ModemTypeCode:String);
var
sp:TIBStoredProc;
tran:TIBTransaction;
begin
tran:=TIBTransaction.Create(nil);
tran.DefaultDatabase:=FDatabase; // экземпляр базы данных потока
sp:=TIBStoredProc.Create(nil);
sp.Database:=FDatabase;
sp.Transaction:=tran;
sp.StoredProcName:='SRV_OBJECTS_SET_MODEMSTYPEID';
try
try
sp.ParamByName('Number').AsString:=Number;
sp.ParamByName('MODEMTYPEID').AsInteger:=ModemTypeId;
sp.ExecProc;
tran.Commit;
WriteLog(0,mess1404,[Number,ModemTypeCode]);
except
on E:Exception do begin
WriteLog(0,mess0053,[E.Message]);
tran.Rollback;
end;
end;
finally
sp.Free;
tran.Free;
end;
end;
Код: Выделить всё
procedure TObjectsInquiryThread.QueryObjects;
var
Query:TIBQuery;
Mess:TMessage;
begin
Query:=TIBQuery.Create(nil);
Query.Database:=FDatabase; // экземпляр базы данных потока
Query.Transaction:=FTransaction;// экземпляр транзакции потока
Query.SQL.Text:=FQueryString;
try
Query.Open;
Mess:=TMessage.Create('InquiryObjectsPriority','');
if not Query.IsEmpty then begin
...
end;
finally
Query.Free;
end;
end;
Код: Выделить всё
const
sTransactionParams=
'read_committed'#13#10+
'rec_version'#13#10+
'nowait';
1. М.б. я имею где-то зависшую транзакцию (блокировку?). Как отловить, какая часть ПО берет в эксклюзивное пользование ресурсы БД?
2. Возможно у меня неверный подход к программной архитектуре. Какие возможны варианты построения служб, использующих Firebird - имеется ввиду использование БД в многопоточных приложениях. Точнее - какие грабли замечены?
3. При динамическом создании компонентов доступа к БД какие параметры устанавливать для БД, транзакции, запроса?
4. Если в потоке созданы IBDatabase и привязанная к нему транзакция, то нужно ли для создаваемого запроса создавать транзакцию или достаточно уже созданной? Практика показывает, что достаточно, но мало ли... (А для ХП получилось, что обязательно создавать транзакцию)
ИБ Аналиста ещё не запускал, попробую сегодня вечером.
Спасибо