![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Почему может виснуть многопоточный сервер приложений? [D6, IB6.x]
Дмитрий Жуков © (2002-07-23 11:59:00)На D6 написан сервер приложений, к которому подключаются
несколько клиентов через DCOMConnection или SocketConnection.
Каждый клиент работает со своим RemoteDataModulem, на котором
есть свой Tdatabase и свой TSession. Базой данных является
InterBase 6.0. Также на сервере есть общий DataModul со своим
TDatabase, доступ к TQuery которого для всех потоков реализован
через критическиую секцию.
И вот вся эта конструкция периодически виснет в самые произвольные моменты работы с обхектами типа TQuery. Подскажите, пожалуйста, из-за чего это может происходить?
Дмитрий Жуков (2002-07-25 15:55:00) [1]Имеется ввиду, что для каждого клиента будет запускаться свой
сервер приложений на машине клиента - тогда никакого
многопоточного доступа не будет, => не будет и таких проблем.
Согласен, способ хреновый, то пускать на сервере все потоки через
очередь к одному Tdatabase еще хуже. Так хоть на остальных
СУБД все будет работать по-человечески.
Digitman (2002-07-25 14:01:00) [2]Как это - "при работе с InterBase каждому клиенту
ставить сервер приложений" ? Поясни ... Зачем клиенту что-то ставить кроме кл.части ? ты что используешь - TSocketConnection ? Или ?
Дмитрий Жуков (2002-07-25 13:55:00) [3]А чем тогда обяснить следующий эксперимент:
я переписал этот пример (по совету одного
"специалиста" из Borland.ru) на dbExpress. Теперь
сервер тоже вылетает, но уже с ошибкой
Error writing data to connection
вместо
Error reading data from connection
которая была на BDE. Как говориться, те же яйца,
только в профиль.
В критических секциях тоже все работает.
А на Oracle работает при любых условиях. Под MS SQL
проверить не смог, т.к. его dbExpress просто не
поддерживает.
На InterBase API я писать, к сожалению, не могу,
т.к. универсальность мне просто необходима. Похоже,
придется при работе с InterBase каждому клиенту
ставить сервер приложений.
Это просто праздник какой-то...
Digitman (2002-07-25 12:53:00) [4]>Дмитрий Жуков
Это - BDE. Понимаю, что лишишься универсальности при проведении подобных экспериментов, но все же - рискни обойтись без BDE, используюя либо непосредственно API либо компоненты прямого доступа к тем сиквел-серверам, которые ты сравниваешь при тестировании на предмет "глюков". Это все же будет гораздо более "чистый" эксперимент
erik (2002-07-25 11:56:00) [5]Скорее всего Interbase тут непричем, это BDE дайвер для Interbase глючит. Его еще линком называют.
Дмитрий Жуков (2002-07-25 10:16:00) [6]Для тех, кому интересно.
Данный пример заработал только после того, как я ВСЕ
действия, связанные с TQuery, заключил в критическую секцию.
Какие "гении" этот InterBase писали?!!!!
Дмитрий Жуков (2002-07-24 17:47:00) [7]Да ладно... Я так чувствую, что и не моя тоже...:-(
Людииии!!!!!! Аууууууу!!!!!! Тут есть спецы по BDE и InterBasу?
Набережных С. (2002-07-24 17:40:00) [8]Ну тады упс Не моя тема, извиняй:)
Дмитрий Жуков (2002-07-24 17:33:00) [9]да
Случайный прохожий (2002-07-24 17:28:00) [10]А Session1.AutoSessionName установлено в true?
Дмитрий Жуков (2002-07-24 16:04:00) [11]а под ms sql и Oracle этот пример работает, даже если туда добавить код, использующий общий для всех потоков TDatabase и TSession.
Дмитрий Жуков (2002-07-24 15:58:00) [12]вот что я дергаю:
procedure TTestRDM.Delete;
var q: TQuery;
i: integer;
begin
q := TQuery.Create(Self);
try
q.SessionName := Session1.SessionName;
q.DatabaseName := Database1.DatabaseName;
i := Random(1000000);
q.SQL.Text := "DELETE FROM TEST123 WHERE F1 = "+ IntToStr(i);
q.ExecSQL;
finally
q.Free;
end;
end;
procedure TTestRDM.Update;
var q: TQuery;
i: integer;
begin
q := TQuery.Create(Self);
try
q.SessionName := Session1.SessionName;
q.DatabaseName := Database1.DatabaseName;
i := Random(1000000);
q.SQL.Text := "UPDATE TEST123 SET F2 = ""UPDATED"" WHERE F1 = "+ IntToStr(i);
q.ExecSQL;
finally
q.Free;
end;
end;
procedure TTestRDM.ClientSelect;
var i, j, f1: integer;
wst: string;
dat1: TDateTime;
q: TQuery;
begin
q := TQuery.Create(Self);
try
q.SessionName := Session1.SessionName;
q.DatabaseName := Database1.DatabaseName;
with q do
begin
SQL.Text := "SELECT * FROM TEST123";
i := Random(200);
j := 0;
Close;
Open;
while (not eof) and (j < i) do
begin
inc(j);
f1 := Fieldbyname("F1").AsInteger;
wst := Fieldbyname("F2").AsString;
dat1 := Fieldbyname("F3").AsDateTime;
next;
end;
locate("F1", i, []);
end;
finally
q.Free;
end;
end;
больше там ничего нет, кроме стандартных
class procedure TTestRDM.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;
initialization
TComponentFactory.Create(ComServer, TTestRDM,
Class_TestRDM, ciMultiInstance, tmApartment);
end.
Digitman (2002-07-24 14:01:00) [13]>Дмитрий Жуков
Интересная ассоциация получается : ты чего-то там "дергаешь", а IB-сервер крайним остается) ....
Дмитрий Жуков (2002-07-24 13:45:00) [14]Господа!
А как объяснить следующий факт?
Наваял я примерчик сервера с RemoteDatamodulem, в котором
есть несколько ф-ций, дергающих базу. У каждого TDatabase свой TSession, созданный этим же потоком. Т.е. все выполнено по правилам. Так вот при обращении нескольких клиентов на сервере через какое-то время при выполнении TQuery.open и TQuery.execSQL вылетает ошибка:
Error reading data from connection
По этой ошибке постепенно отваливают все клиенты, пока не
остается один, которому больше всех повезло - теперь в одиночестве он может работать до бесконечности.
А теперь внимание: при работе с MS SQL Server 2000 или
Oracle 9i никаких ошибок и подвисаний не возникает даже
если они работают с общими TQuery через критические секции!
Получается, проблемы именно в InterBase!
Набережных С. (2002-07-24 11:55:00) [15]
> Polevi © (24.07.02 11:27)
Да сорри,
За что?!!!!
> Digitman © (24.07.02 11:29)
Ну разумеется, я разве спорю? Я и сам немало "поизвращался" в этой области :)Я говорил(смею подчеркнуть:)) о стандартной схеме.
Digitman (2002-07-24 11:29:00) [16]>Набережных С. (24.07.02 11:03)
Все правильно. Так это и работает. С той лишь деталью (смею подчеркнуть), что никто и ничто не мешает реализовать фабрику класса AppServer"а как фабрику internal-объектов. Обидно то, что Борланд не предусматривает это, обращаясь (при реализации всей этой цепочки) только к обязательно зарегистрированным в реестре фабрикам классов и к станд.механизму поиска фабрики и ее инициализации (COM-механизму самой ОС)
Polevi (2002-07-24 11:27:00) [17]2Набережных С.
Да сорри, это основы основ - я понял это заглянув в VCLCom
Буду думать, спасибо
Digitman (2002-07-24 11:22:00) [18]>Дмитрий Жуков
Извини, но я понятия не имею о "нормальности" или "ненормальности" чего-то там в Oracle и MSSQL.. На практике я не работал с этими сиквэл-серверами, поэтому судить не берусь. Но интуитивно могу предположить, что и в этих системах (как, впрочем, и в иных сиквэл-серверных системах в арх-ре SuperServer) эти особенности так же имеют место быть...
Вот то, что я поимел из офиц. и неофиц. источников по ПО IB и попробовал собственными руками - о том и смею говорить.
Набережных С. (2002-07-24 11:03:00) [19]
> Polevi © (24.07.02 09:37)
Может, я по-старости окончательно поглупел, однако, по-моему, это не совсем то. Метод CoCreateInstance - стандартный метод библиотеки СОМ.
Он производит поиск и, если не найдет, создание необходимой фабрики классов(опускаем несущественные в нашем случае нюансы), после чего вызывается ее метод CreateInstance. Далее в действие вступает (в случае стандартной реализации Borland и при применении TRemoteDataModule) класс TComponentFactory, точнее, его метод CreateInstance, который собственно и создает СОМ-объект в соответствии с выбранной потоковой моделью и типом сервера, и возвращает интерфейс обратно по цепочке. Если объект реализован в DLL, то он создается в том потоке, который вызвал метод CoCreateInstance. Созданный COM-объект, в свою очередь, создает нашего потомка TRemoteDataModule и является для него контейнером. Т.е., с точки зрения СОМ, TDataBlockInterpreter.CreateObject - это клиентский конец цепи. Как-то даже странно... это ведь основы основ. Или где?
Дмитрий Жуков (2002-07-24 10:54:00) [20]2Digitman
А можно поподробнее насчет "что источник инф-ции - офиц.документация по ПО InterBase". Вы хотите сказать, что скажем под MS SQL или Oraclom это будет работать нормально?