Название: [РЕШЕНО] connection pool плюсы и минусы Отправлено: unkeep от Март 29, 2016, 17:41 Какие минусы использования пула соединений при многопоточной работе с бд(соединение создаётся для каждого потока)?
В общем случае, на сколько я понимаю, жертвуя памятью получаем прирост скорости за счёт повторного использования открытого соединения. Но может быть есть ещё нюансы, например зависимость скорости соединения от их количества? Название: Re: connection pool плюсы и минусы Отправлено: Old от Март 29, 2016, 17:48 Какие минусы использования пула соединений при многопоточной работе с бд(соединение создаётся для каждого потока)? Минусов не знаю, сам так делаю. :)Название: Re: connection pool плюсы и минусы Отправлено: unkeep от Март 29, 2016, 17:54 Есть ли смысл закрывать соединение если им долгое время не пользуются?
Название: Re: connection pool плюсы и минусы Отправлено: Old от Март 29, 2016, 18:00 Есть ли смысл закрывать соединение если им долгое время не пользуются? Нет. Зачем? А если сразу после закрытия понадобиться выполнить запрос? :)Как правило, рабочих потоков работающих с БД много не запускают, ну будет открыто 8 соединений... Название: Re: connection pool плюсы и минусы Отправлено: unkeep от Март 30, 2016, 10:11 можно код ревью?
ConnectionPool.h Код
ConnectionPool.cpp Код
Название: Re: connection pool плюсы и минусы Отправлено: Old от Март 30, 2016, 10:28 Бегло просмотрел, что сразу бросилось в глаза.
В методе getConnectionForThread вы защищаете мьютексом только добавление нового соединения, хотя нужно и поиск с извлечением защищать. Для этого может пригодиться QReadWriteLock. Теперь вообще по концепту. Я сразу создаю пул рабочих потоков и каждому потоку сразу создаю соединение. Потоки и соединения живут весь период жизни пула. Название: Re: connection pool плюсы и минусы Отправлено: unkeep от Март 30, 2016, 11:19 с учётом замечаний по синхронизации
Код
А концепции у нас разнятся, так как в текущей задаче используется пул потоков. Чаще всего вызывается getConnection() в методе, вызванном с помощью QtConcurrentRun. Название: Re: connection pool плюсы и минусы Отправлено: Old от Март 30, 2016, 12:01 Да, QReadWriteLock, в отличие от бустовских аналогов, не позволяет изменять роль, т.е. стать из читателя писателем. Я его посоветовал, но сейчас забираю свой совет обратно, по крайней мере пока его не доработают. :)
Лучше обойтись простым мьютексом. Код
Название: Re: connection pool плюсы и минусы Отправлено: ballard от Декабрь 14, 2016, 18:36 Теперь вообще по концепту. Я сразу создаю пул рабочих потоков и каждому потоку сразу создаю соединение. Потоки и соединения живут весь период жизни пула. можно посмотреть код такой реализации? Название: Re: connection pool плюсы и минусы Отправлено: ballard от Декабрь 20, 2016, 14:23 Бегло просмотрел, что сразу бросилось в глаза. В методе getConnectionForThread вы защищаете мьютексом только добавление нового соединения, хотя нужно и поиск с извлечением защищать. Для этого может пригодиться QReadWriteLock. Теперь вообще по концепту. Я сразу создаю пул рабочих потоков и каждому потоку сразу создаю соединение. Потоки и соединения живут весь период жизни пула. на самом деле интересует организация много-поточного доступа к коннекшенам, я пробовал делать воркеры, наследуемые от QThread, но тогда непонятно как сделать метод запроса с возвращаемым результатом, так же пробовал выполнять запросы в QtConcurrent, но тут проблема в том, что соединение созданное при помощи QSqlDatabase::addDatabase должно вызываться из того же потока в котором создано, т.е. хотя бы архитектура "на пальцах" или в псевдокоде, если не хочется раскрывать свое исполнение Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 20, 2016, 15:09 Для каждой нитки можно клонировать подключения.
Таких клонов может быть столько, сколько есть рабочих ниток. В каждой нитке свое подключение. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 20, 2016, 23:35 Для каждой нитки можно клонировать подключения. Таких клонов может быть столько, сколько есть рабочих ниток. В каждой нитке свое подключение. Большое спасибо за ответ! А можно показать в виде кода, о чем речь (хотя бы частично)? У меня пока такая конфигурация (если можно, код ревью, критику и т.д. :) ): Пул создает набор воркеров (вместо clone делает addDatabase с именем, хотя в документации сказано, что в этом случае нужно обращаться к БД из того потока к котором вызывался addDatabase, но пока сбоев не было, может здесь что-то изменилось) и просто по очереди передает им запросы (в дальнейшем есть мысли прикрутить сюда что-то типа consumer-producer), в принципе работает при обращении к пулу из разных потоков и без QMutex, но на всякий случай его пока оставил. Хочется создать набор соединений и выполнять к нему запросы вида QSqlQuery executeQuery(const QString &query), причем накидать сразу много запросов, чтобы они по очереди выполнились... и, вроде бы, все работает, но возможно есть какие-то проверенные временом типовые решения, или в дальшейшем я встречу какие-то проблемы. Просто очень заинтересовала упомянутая реализация концепта, именно к такой и стремлюсь. p.s. вроде нашел проблему, с вызовами из разных потоков непонятная ситуация Пул: pool.h Код: class DBConnectionPool : public QObject pool.cpp Код: DBConnectionPool::DBConnectionPool(const PoolConfig &config, QObject *parent) : QObject(parent) Воркер: worker.h Код: class DatabaseWorker : public QObject worker.cpp Код: void DatabaseWorker::init() Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 23, 2016, 11:56 есть ли какие-нибудь замечания/советы по реализации? (очень хотелось бы услышать) :) Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 23, 2016, 21:25 есть ли какие-нибудь замечания/советы по реализации? (очень хотелось бы услышать) :) А у вас этот код нормально работает?Как-то для меня не очень понятен запуск функции в отдельном потоке и блокировка вызывающего потока? Если вы его все равно блокируете, так в нем лучше и выполняйте функцию? Но вы все усложняете, достаточно запустить воркеры и организовать для них одну очередь запросов, по мере освобождения воркеры будут брать запросы из очереди или заснут, пока не появятся новые запросы. Организация таких очередей 100500 раз обсуждалась на форуме, поищите, там и примеры были. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 23, 2016, 21:32 есть ли какие-нибудь замечания/советы по реализации? (очень хотелось бы услышать) :) А у вас этот код нормально работает?Как-то для меня не очень понятен запуск функции в отдельном потоке и блокировка вызывающего потока? Если вы его все равно блокируете, так в нем лучше и выполняйте функцию? Но вы все усложняете, достаточно запустить воркеры и организовать для них одну очередь запросов, по мере освобождения воркеры будут брать запросы из очереди или заснут, пока не появятся новые запросы. Организация таких очередей 100500 раз обсуждалась на форуме, поищите, там и примеры были. Спасибо Вам! Посмотрю конечно в поиске про очереди, т.к. именно так как выделено я и хочу сделать, но просто гуглопоиск на эту тему ни к чему не привел...поэтому и обратился :) если вдруг вспомните ссылки, подскажите про них) Я смотрел примеры qt waiting condition и semaphore, думал копать в эту сторону) ну и как я уже писал, за любые примеры, даже псевдокодом буду очень признателен :) Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 23, 2016, 21:45 http://www.prog.org.ru/topic_23820_0.html
http://www.prog.org.ru/topic_27817_0.html http://www.prog.org.ru/topic_29697_0.html http://www.prog.org.ru/topic_14426_0.html http://www.prog.org.ru/topic_12552_0.html Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 24, 2016, 00:04 Еще раз спасибо! на самом деле многое обсуждалось) проштудирую ссылки и выложу свое обновленное решение :) Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 25, 2016, 02:03 Но вы все усложняете, достаточно запустить воркеры и организовать для них одну очередь запросов, по мере освобождения воркеры будут брать запросы из очереди или заснут, пока не появятся новые запросы. Организация таких очередей 100500 раз обсуждалась на форуме, поищите, там и примеры были. Просмотрел ссылки, а так же проглядел раздел про многопоточности, но так и не получается сформировать цельное представление... Как лучше организовать очередь? через semaphore? или через qqueue... Как быть с воркерами? qtconcurrent + future как мне казалось подходят потому что позволяют организовать синхронную блокирующую функцию типа QSqlQuery executeQuery (const QString& query) {...} , если делать воркеры через qthread, например, то возврат результата можно реализовать только через сигналы-слоты...это не то, что нужно, хотя может быть я и ошибаюсь Идеально было бы реализовать вариант с забором запросов из очереди и засыпанием, но здесь уже, вроде бы надо использовать qwaitcondition? как-то разные части задачи делаются разными способами, а как их совместить пока не вижу... Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 25, 2016, 02:27 Как лучше организовать очередь? через semaphore? или через qqueue... QList+QWaitConditionкак-то разные части задачи делаются разными способами, а как их совместить пока не вижу... А на что там остается смотреть? :)Вот простейший пример очереди задач: http://www.prog.org.ru/index.php?topic=14426.msg95463#msg95463 Клиент(ы) в нее добавляют задания, а ворер(ы) достают и обрабатывают. Результат отдают через сигнал. Все это добро (очередь и нитки-воркеры) прячется за классом пул, в который можно добавлять запросы, а при получении ответа он эмитит сигнал. Если нужны еще и синхронные запросы, то это делается не через воркеры, а синхронным запросом через отдельное подключение. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 25, 2016, 21:27 QList+QWaitCondition А на что там остается смотреть? :) Вот простейший пример очереди задач: http://www.prog.org.ru/index.php?topic=14426.msg95463#msg95463 Клиент(ы) в нее добавляют задания, а ворер(ы) достают и обрабатывают. Результат отдают через сигнал. Все это добро (очередь и нитки-воркеры) прячется за классом пул, в который можно добавлять запросы, а при получении ответа он эмитит сигнал. Если нужны еще и синхронные запросы, то это делается не через воркеры, а синхронным запросом через отдельное подключение. Спасибо! Т.е. я правильно понял, что либо пул, либо синхронный запрос? Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 25, 2016, 21:32 Спасибо! Т.е. я правильно понял, что либо пул, либо синхронный запрос? Скорее, либо другие нити, либо синхронный запрос.Синхронный запрос подразумевает, что вы запускаете выполнение этого запроса в текущей нитке и ожидаете его завершения. Параллельные потоки могут выполнять несколько запросов одновременно. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 25, 2016, 21:40 Скорее, либо другие нити, либо синхронный запрос. Синхронный запрос подразумевает, что вы запускаете выполнение этого запроса в текущей нитке и ожидаете его завершения. Параллельные потоки могут выполнять несколько запросов одновременно. В принципе, наверное, можно передавать какой-то идентификатор в запрос, чтобы вернуть его через сигнал, для определения, кому он предназначен... Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 10:18 Скорее, либо другие нити, либо синхронный запрос. Можете еще вот эту фразу пояснить? Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 26, 2016, 10:27 Можете еще вот эту фразу пояснить? Пул просто более высокоуровневое понятие, чем нить.Для синхронного запроса уже нить избыточна, а пул нитей и подавно. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 10:30 Пул просто более высокоуровневое понятие, чем нить. Для синхронного запроса уже нить избыточна, а пул нитей и подавно. Так вот и вопрос, есть ли способ организовать доступ выполнение синхронных запросов из разных потоков при помощи одного коннекшена, либо их набора с очередью для запросов...? Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 26, 2016, 10:36 Так вот и вопрос, есть ли способ организовать доступ выполнение синхронных запросов из разных потоков при помощи одного коннекшена, либо их набора с очередью для запросов...? Сформулируйте, что понимаете под синхронными запросами.Вы хотите выполнять серию запросов в определенном порядке? Тогда самое просто изменить ваш пул так, что бы он принимал не строку запроса, а массив строк (QStringList). А нитки-воркеры в цикле их выполняли. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 10:44 Сформулируйте, что понимаете под синхронными запросами. Вы хотите выполнять серию запросов в определенном порядке? Тогда самое просто изменить ваш пул так, что бы он принимал не строку запроса, а массив строк (QStringList). А нитки-воркеры в цикле их выполняли. Я хочу сделать так, чтобы у моего пула, хотя это скорее уже не пул, а что-то большее, но не суть, был один публичный метод, типа: Код: QSqlQuery executeQuery(const QString &query); который бы располагал такие запросы в очереди, а свободные воркеры их из нее забирали и обрабатывали. При этом мне нужна возможность обращаться к пулу из разных потоков. Я, в принципе, понимаю, как это сделать через сигнал-слот, но можно ли сделать метод возвращающий результаты запроса в таком виде пока не пойму... Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 26, 2016, 11:05 который бы располагал такие запросы в очереди, а свободные воркеры их из нее забирали и обрабатывали. Ну так мы сейчас именно это и обсуждаем. Для этого нужны несколько рабочих ниток и очередь запросов (QList+QWaitCondition).При этом мне нужна возможность обращаться к пулу из разных потоков. Все. Я, в принципе, понимаю, как это сделать через сигнал-слот, но можно ли сделать метод возвращающий результаты запроса в таком виде пока не пойму... А результат можно возвращать с помощью сигнала, добавив каждому запросу некий ID.Код
Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 11:58 Ну так мы сейчас именно это и обсуждаем. Для этого нужны несколько рабочих ниток и очередь запросов (QList+QWaitCondition). Все. А результат можно возвращать с помощью сигнала, добавив каждому запросу некий ID. Код
Сейчас еще такая мысль есть, а что если мне в QList заданий для воркеров класть QFuture, и пусть у меня при вызове из одного потока запрос будет блокирующий, т.е. пока текущий не завершится следующий не поступит на исполнение? а из других потоков задания будут проходить Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 26, 2016, 12:06 Если вы блокируете текущую нить на время выполнения запроса, то не понятно для чего его выполнять в другой нитке. Ну и выполняйте этот запрос сразу в текущей? ???
Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 12:09 Если вы блокируете текущую нить на время выполнения запроса, то не понятно для чего его выполнять в другой нитке. Ну и выполняйте этот запрос сразу в текущей? ??? Изначально суть в том, как вы понимаете, чтобы открыть и держать открытыми несколько соединений с БД. Если я блокирую какую-то одну нитку, то остальные остаются свободны для обращения из других потоков. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 26, 2016, 12:23 Изначально суть в том, как вы понимаете, чтобы открыть и держать открытыми несколько соединений с БД. Так откройте сразу 10 соединений и используйте их. Зачем вам рабочие нитки?Если я блокирую какую-то одну нитку, то остальные остаются свободны для обращения из других потоков. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 12:30 Так откройте сразу 10 соединений и используйте их. Зачем вам рабочие нитки? Всмысле открывать сразу в вызывающих потоках? или вы что имеете в виду? Идея такая, что у меня может быть к примеру 20 вызывающих при 5 открытых нитках в пуле, но каждых из этих 20-ти будет класть по задания последовательно, после выполнения предыдущего Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 26, 2016, 12:43 Всмысле открывать сразу в вызывающих потоках? или вы что имеете в виду? Пожалуйста, пулу все равно, дожидается ли клиент отработки предудущего запроса или нет.Идея такая, что у меня может быть к примеру 20 вызывающих при 5 открытых нитках в пуле, но каждых из этих 20-ти будет класть по задания последовательно, после выполнения предыдущего Нужно ждать хорошо, не нужно - тоже хорошо. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 13:47 Пожалуйста, пулу все равно, дожидается ли клиент отработки предудущего запроса или нет. Нужно ждать хорошо, не нужно - тоже хорошо. Ну да, но получается мне нужно как раз организовать промежуточный класс между вызывающими потоками и пулом, у которого и будет нужный мне метод, возвращающий QSqlRequest, Вы это имеете в виду? Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: Old от Декабрь 26, 2016, 13:53 Ну да, но получается мне нужно как раз организовать промежуточный класс между вызывающими потоками и пулом, у которого и будет нужный мне метод, возвращающий QSqlRequest, Вы это имеете в виду? Да, он будет запускать нитки-воркеры и нагружать их работой (через очередь), в ответ сигналя о результатах. Как у вас и было реализовано.Добавьте в него очередь и все. Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 26, 2016, 13:55 Да, он будет запускать нитки-воркеры и нагружать их работой (через очередь), в ответ сигналя о результатах. Как у вас и было реализовано. Добавьте в него очередь и все. Ok, спасибо, буду делать, потом поделюсь результатом :) Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 27, 2016, 00:34 В общем что-то нет прогресса с очередью :-\ Только сделал так выполнение запроса (QueryWrapper - это обернутый QSqlRequest): Код
Очередь непонятно, как сюда прикрутить: т.к., например future создается через qtconcurrent::run, который сразу исполняет запрос и, соответственно, в QList для некого воркера future не добавить. Т.е. для синхронного запроса с очередью мне нужно что-то типа: Код
taskList это как раз qlist из которого некий consumer заберет запрос и выполнит Пока что не понимаю, можно ли это сделать, и, если да, то как ??? Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 27, 2016, 14:08 Да, он будет запускать нитки-воркеры и нагружать их работой (через очередь), в ответ сигналя о результатах. Как у вас и было реализовано. Добавьте в него очередь и все. В общем-то пришла идея сделать эту функцию блокирующей, и тогда можно встроить работу с очередью. Либо по таймауту, либо цикл с проверкой выполнения запроса, либо через Qt::BlockingQueuedConnection, как Вы думаете, какой вариант лучше? Код
Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 27, 2016, 23:43 В общем сделал пока вариант с одним воркером...из одного потока пока все работает. Блокирующая функция выполняется. Можете посмотреть момент с ::run() у QueryThread и по Tasking, все ли верно? worker.h Код
worker.cpp Код
querythread.h Код
querythread.cpp Код
tasking.h Код
tasking.cpp Код
pool.h Код
pool.cpp Код
Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 27, 2016, 23:59 Теперь надо еще продумать, как идентифицировать сигналы от разных воркеров, при обращении из разных потоков
Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 28, 2016, 16:32 А результат можно возвращать с помощью сигнала, добавив каждому запросу некий ID. Код
Обновил пул для работы с несколькими воркерами, можете посоветовать, как вернуть данные именно от того воркера, которому отправлен запрос? Код
Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 28, 2016, 17:17 В общем добавил пока сортрировку следующим образом, записывая запрос , блокируя мьютексом и проверяя потом на совпадение, но с таким способом пул зависает через несколько запросов, которые производятся из разных потоков, похоже из-за мьютекса возникает deadlock, без блокирования мьютексом запросы идут нормально, но, естественно порядок не совпадает...что тут можно сделать? :
Код
Название: Re: [РЕШЕНО] connection pool плюсы и минусы Отправлено: ballard от Декабрь 28, 2016, 21:10 все, вроде бы победил: сделал мапу с результатами :)
Код
|