![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поведение ADOConnection в многопоточном приложении [MSSQL]
Ega23 © (2005-11-08 16:46:00)Ситуация следующая:
Есть некая система с достаточно большим количеством объектов. У каждого из объектов есть поле Status, и это свойство изменяется в реальном времени по неким событиям (как из пользовательского интерфейса, так, например, и по сетевому событию). Каждый из этих объектов имеет своё отображение в БД.
Теоретически, событие обновления статуса объекта должно происходить по-принципу "плюнул и забыл", т.е. не нужно дожидаться выполнения команды.
В реальной же жизни приложение всё-таки ждёт результат выполнения ADOQuery.ExecSQL, что естественно сказывается на времени обработки сообщения.
После некоторых раздумий было принято решение вынести обновления статусов объектов в отдельный поток. Но тут встала другая проблема: все запросы работают через один ADOConnection, у которого есть свойство State. И которое далеко не всегда только stOpen.
В связи с этим возникает вопрос: как можно обойти данную проблему? Плодить отдельный коннект на каждый поток? Проверять статус ADOConnection во всех потоках? Писать наследника от TADOQuery, где анализировать изменение ADOConnection.State?
В общем, поделитесь мыслями...
Johnmen (2005-11-08 23:19:00) [21]>Ega23 ©
А чем смущает "каждому потоку - свой коннект" ?
Ega23 (2005-11-08 18:50:00) [22]
> А если один коннект для "сосёт" из БД различные выборки
> и один для "плюнул и забыл"
Если мне не изменяет память, то в MSDE есть ограничение на число коннектов к БД. Плюс разные пространства выполнения для каждого из ProcessID. Тоже, в общем-то, грабли...
Нет, конечно, если с одим коннектом ничего сделать нельзя, то будем дополнительный вводить. А точнее, как минимум 2 - один для обновления оперативных состояний, второй - для протоколирования данных.
Но лучше всё-таки через один найти решение...
Плохиш (2005-11-08 18:35:00) [23]
> Ega23 © (08.11.05 17:54) [10]
> Вот-вот. Я тоже придерживаюсь такого мнения. Проблема в
> том, что основное приложение "сосёт" из БД различные выборки,
> причём достаточно часто. И при этом некая часть этого приложения
> (тот самый дополнительный поток) работает как "плюнул и
> забыл".
А если один коннект для "сосёт" из БД различные выборки и один для "плюнул и забыл"
isasa (2005-11-08 18:29:00) [24]Ega23 © (08.11.05 18:26) [28]
Ну так ...
И серверный курсор. И вперед ... А я домой.
Ega23 (2005-11-08 18:28:00) [25]
> оптимизация уже написаного приложения, вообще интересный
> кусок работы
Это нормально. Нельзя же было ещё на этапе проектирования такие вещи учесть. Вот сейчас статистику работы наберём и будем анализировать.
Ega23 (2005-11-08 18:26:00) [26]
> Ема-е ну сколько времени занимает транзакция с обновлением
> одной записи в индексированой таблице.
>
15 мс. Это нормально. Но в основном потоке, где один такт порядка 100 мс - это уже много.
Silver Alex (2005-11-08 18:25:00) [27]>>Ega23 © (08.11.05 18:18) [23]
понимаю :)
оптимизация уже написаного приложения, вообще интересный кусок работы
isasa (2005-11-08 18:23:00) [28]Да, что-то притормозил. Домой пора.
А в общем коннекте ты не сможеш поиграться с CursorLocation.
А нодо бы, по идее.
Silver Alex (2005-11-08 18:22:00) [29]>>Bronco © (08.11.05 18:14) [21]
не думаю что создание дополнительных коннектов ускорит работу, так как для их создания/удаления тоже потребляются ресурсы.
И еще раз повторюсь, вот как сразу видно что все работают на пиратском ПО, никто даже не задумывается что лишние конекты выльются заказчику в лишние деньги
isasa (2005-11-08 18:20:00) [30]Ega23 © (08.11.05 18:14) [22]
Ема-е ну сколько времени занимает транзакция с обновлением одной записи в индексированой таблице.
Ega23 (2005-11-08 18:18:00) [31]
> делаешь там все через Synchronize ?
Это вообще не я делаю. Это коллега мучается. На мне - серверная часть.
Просто сейчас тестируем альфа-версию релиза. Получили серьёзные "тормоза" при моделировании пиковой загрузки системы. Вот пытаемся оптимизировать. Я на сервере индексы строю, Лёха вот с потоком экперементирует... :о)
Ega23 (2005-11-08 18:14:00) [32]
> Каждый поток имеет свое соединение. Иначе нарываемся на
> ряд вопросов.
> 1.Кто открывает соединение?
> 2.Кто закрывает соединение?
> 3.Маршаллинг соединения в поток(если надо, а может не надо)?
>
>
1. Основной поток при старте.
2. Основной поток при закрытии.
3. Дык не проблема...
Коннект - это тоннель к базе, по которому гоняются составы-транзакции. Если поток один - всегда в тоннеле будет только один состав. Или "туда", или "сюда". А вот если потока 2, то есть вероятность столкновения этих составов. Таким образом, нужен или новый тоннель для дополнительного потока, либо семафор на главном. В качестве семафора можно использовать ADOConnection.State
В силу ряда причин не хочется иметь на сервере несколько разных процессов. Поэтому работа с одним коннектом - более предпочтительна.
Bronco (2005-11-08 18:14:00) [33]
> Ega23 © (08.11.05 17:56) [12]
>
>
> Да потому, что это на N запросов получается N коннектов.
> И на сервере у каждого из них СВОЙ ProcessID.
А я вобще с трудом себе представляю работу N потоков через один коннект.
Тем более, если важна скорость, сам бог велел создать N коннектов.
Потому как даже если сделать всю работу с данными потокобезопастной, как предложили в [18], то это так же будет отъедать время (ожидание завершения)
isasa (2005-11-08 18:14:00) [34]Ega23 © (08.11.05 18:08) [17]
Точно сделал-бы с отдельным потоком + TADOQuery.ConnectionString + CursorLocation:=clServer; ИМХО
Silver Alex (2005-11-08 18:12:00) [35]>>Ega23 © (08.11.05 18:08) [17]
делаешь там все через Synchronize ?
isasa (2005-11-08 18:10:00) [36]Да, еще :)
Традиционно.
4. Совместное использование (возня с критическими секциями)?
Ega23 (2005-11-08 18:08:00) [37]
> не понял, что такое прототип? обрисуй ситуации конкретней
> как-то, что за обьекты, что за события. Когда надо вызывать,
> что записывать в базу или читать. "Connection is busy"
> когда именно вываливается?не думаю что это TADOConnection,
> ни разу не встречал.Может сам сервер, хотя утверждать не
> буду. Надо больше информации
>
Под прототипом я имел ввиду добавление дополнительного потока.
Блин, долго объяснять.
В общем так: есть система безопасности. Всякие датчики-фигатчики и т.п. Всё это завязано в сеть. И есть АРМ (автоматизированное рабочее место) мониторинга системы. Там красивая графика, всякие гриды и прочие пользовательские прибамбасы. Суть работы такова: какой-то датчик изменил своё состояние (допустим из "нормального" в "тревожное"). Контроллер датчика отправляет это сообщение в сеть. АРМ его ловит, определяет кому оно адресовано, изменяет статус данного датчика в БД (это тот самый дополнительный поток) и отображает изменение состояния на экране. А, ещё протоколирует это дело.
Так вот, на update состояния съедается порядка 15 мс. В принципе это нормально, но если запускать этот update из основного потока приложения, то эти 15 мс. приложение ждёт ответа. А это уже нехорошо.
При попытки вынесения этих update-тов в отдельный поток нарвались на исключение Connection is busy. Т.е. что-то в этот момент времени выполнялось через данный коннект из основного приложения.
isasa (2005-11-08 18:06:00) [38]Я не понимаю, что смущает?
Каждый поток имеет свое соединение. Иначе нарываемся на ряд вопросов.
1.Кто открывает соединение?
2.Кто закрывает соединение?
3.Маршаллинг соединения в поток(если надо, а может не надо)?
Ставим себе барьеры и мужественно их преодолеваем? :)
Silver Alex (2005-11-08 18:02:00) [39]>>isasa © (08.11.05 17:56) [13]
>>А если потоков много. ISAPI, например.
если нельзя, но очень надо, то конечно можно :)
а если лицензий на базу пять штук и работает пять человек, то как тогда быть , если твоя прога может наплодить кучу коннектов? Думаю надо по ситуации смотреть, но вообще достаточно для одной программы одого коннекта, имхо
isasa (2005-11-08 17:59:00) [40]Да потому, что это на N запросов получается N коннектов.
Один поток - одно коннекшн.
Много потоков - много коннекшн.