-
Суть вопроса: есть дополнительные потоки, задача которых считать данные со всяких железок. После чтения эту информацию необходимо сохранить в БД. На этапе разработки решил считанные данные из дополнительных потоков передавать основному, который и будет делать записи в БД. После запуска проекта выяснилось, что доп.потоков может быть много и основной поток не успевает все это записывать. Появляется очередь. Дополнительные потоки вынуждены ждать основной, чтобы ему передать данные.
В связи с этим вопрос. А как правильно все это спроектировать? Прямо из дополнительных потоков обращаться к базе? Или вместо главного (где сейчас запись в БД) сделать еще несколько потоков исключительно для работы с БД?
Спасибо.
P.S. По правде говоря, никогда не работал с БД из дополнительных потоков. Насколько я понимаю, использовать компоненты там нельзя. Дополнительный вопрос: как работать с БД из доп. потока? Может захудалый пример кода найдется...
-
Дополнительные потоки вынуждены ждать основной
если там очередь, то нафига им что-то ждать?
взял показания, отдал потоку-вставлятелю, ушел забирать новые данные.
а если еще основной будет делать инсерты не построчно, а пакетно, то все будет окей
-
генеришь тысячу "добывающих" потоков.
кажный из них считав порцию данных постит их sql потоку.
sql поток, получив новую порцию данных, приклеивает их к xml буферу.
когда данных в xml набралось скажем тысячу штук или просто прошло скажем пять секунд, sql поток делает один параметрический инсерт в базу. в параметре - накопленный xml блоб данных.
и тогда уже не добывающие потоки будут толпиться у вставляющего,
а вставляющий поток будет скучать в ожидании новых показаний железок.
-
> если там очередь, то нафига им что-то ждать?
Данных много. Передаю их в TObjectList размером (25 на 400). Плюс БД "ушаталась" от такого объема (нет пока возможности сделать backup|restore).
-
ну много и чего?
если данные помещены в очередь, то какого конкретно события дожидается вторичный поток и зачем?
пришел ты на почту, отдал сотруднику конверт или посылку.
он ее принял.
но там еще много других посылок. вообще куча.
ты что после этого, остаешься на почте и наблюдаешь когда оно уйдет?
-
> sql поток делает один параметрический инсерт в базу. в параметре
> - накопленный xml блоб данных.
Хм...я пока в танке и не видел подобного исполнения. Как-то все по старинке, в цикле перебираю TObjectList и делаю инсерты, а потом commit.
А можно минимальный пример такого исполнения с блобом?
-
> если данные помещены в очередь, то какого конкретно события
> дожидается вторичный поток и зачем?
>
Если вторичный поток умирая, разрушит этот TObjectList, то тогда главный вместо TObjectList получит мусор. Поэтому сделал с эвентом. Вторичный поток перед отправкой главному создает эвент, потом отправка (PostMessage), потом ожидание WaitForSingleObject этого эвента. Ну а главный ресетит этот эвент, и только тогда дополнительный может спокойно умереть.
> пришел ты на почту, отдал сотруднику конверт или посылку.
>
> он ее принял.
> но там еще много других посылок. вообще куча.
>
> ты что после этого, остаешься на почте и наблюдаешь когда
> оно уйдет?
Да, поржал конечно ))
-
mssql
declare @idoc int, @body varchar(max);
exec sp_xml_preparedocument @idoc OUTPUT, '<root><row type="price" value="3.62"/><row type="volume" value="0.5"/><row type="temperature" value="36.6"/></root>';
select *
from OPENXML (@idoc, '//row', 1)
with (
sensor_type varchar(50) './@type',
sensor_value varchar(50) './@value'
)
exec sp_xml_removedocument @idoc;
xml литерал заменяешь параметром varchar(max)
ну и это просто селект чтоб посмотреть.
а используешь его в
insert into mytable
(
select * from openxml(....) with(...)
)
-
потом отправка (PostMessage), потом ожидание WaitForSingleObject этого эвента. Ну а главный ресетит этот эвент, и только тогда дополнительный может спокойно умереть.
круто, чо.
как бы потоков два, но выполняются строго последовательно. как будто реально работает только один.
но если бы работал один поток за двоих,
то было бы :
1. быстрее
2. не пришлось бы тратить ресурсы системы на евенты.
-
Ну в общем, подход понял. В главном делать только прием данных и помещать их некий буфер, чтобы дополнительные спокойно умирали без очередей.
А уже этот буфер и записывать как-то. Не понял только про "один параметрический инсерт в базу. в параметре - накопленный xml блоб данных."
-
> mssql
А если firebird?
-
Не понял только про "один параметрический инсерт в базу. в параметре - накопленный xml блоб данных."
чо тут непонятного-то
вставить сто тысяч значений одним запросом - это будет быстрее чем вставить одну тысячу значений одной тысячей запросов
-
а если фиребёрд то все равно передавать один раз блоб и делать инсерты на сервере по блобу.
-
> вставить сто тысяч значений одним запросом - это будет быстрее
> чем вставить одну тысячу значений одной тысячей запросов
Это понятно. Непонятно как это сделать в Firebird. Не видел никогда ранее.
-
Если вторичный поток умирая, разрушит этот TObjectList,
1. зачем это делать ему, если это может сделать вызываемая сторона?
2. зачем вторичному потоку умирать после передачи самому, если потоков по дизайну много (должно быть много)?
почему ему нельзя жить в течении всего времени процесса, и добывать всё новые и новые данные из железа?
-
> когда данных в xml набралось скажем тысячу штук или просто
> прошло скажем пять секунд
если за это время отключится электричество и данные пропадут, будет нехорошо. наверное.
-
> если за это время отключится электричество
если отключится электричество и данные пропадут, то конечно очень важно:
будут ли среди пропавших эта тысяча записей за 5 секунд.
зы.
в spaceX наверное так и была сделана заправочная телеметрия.