Название: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 10, 2016, 16:02 Привет.
Программа работает с SQLite базой. Хочу что бы выборка информации из базы происходила в разных потоках. И так... имеем главный поток UI Главный поток запускает новый поток, в котором идет работа с Базой Данных. Созданый поток после отработки останавливается и уничтожается. Соединение с БД осуществляется в новом созданом потоке при срабатывании слота startProcess Код: QThread* thread = new QThread(); И так вопрос. Если в программе создается лишь 1 поток для получения данных из БД, то все ок. Но если одновременно создаю 2 потока для получения данных из разных БД то получаю ошибку Код: QObject::moveToThread: Current thread (0x2768880) is not the object's thread (0x2768928). Подскажите что не так? P.S.: Данные программа получает из двух потоков без проблем, но меня смущает это сообщение об ошибке, то есть данные хоть и получены, но что то идет не так Название: Re: Работа в SQLite в многопоточном приложении Отправлено: qate от Декабрь 10, 2016, 16:46 объект создается не в том потоке
https://wiki.qt.io/Threads_Events_QObjects хотя проблемы sqlite и многопоточностью и тормозами более обширны, советую сразу передумать Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 10, 2016, 17:02 объект создается не в том потоке https://wiki.qt.io/Threads_Events_QObjects хотя проблемы sqlite и многопоточностью и тормозами более обширны, советую сразу передумать Объект который работает с SQLite создается в новом потоке вызовом сигнала startProcess... иными словами он не перемещается из потока в поток, так что ваше утверждение: объект создается не в том потоке здесь не подойдет. Я мог бы сделать простой проект и сюда загрузить для тестов... Если вы считаете что следует забыть, то как же тогда работать с БД ? в одном потоке всегда? Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 10, 2016, 17:43 С SQLite нельзя работать в несколько потоков, так что, либо однопоточно, либо другая БД.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 10, 2016, 18:00 С SQLite нельзя работать в несколько потоков, так что, либо однопоточно, либо другая БД. Вот это для меня новость... честное слово... ок. А какую БД тогда посоветуете что бы использовать локально на компьютере? Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 10, 2016, 18:11 Я советую postgresql. Честно. Много лет использую его в продашене. Тем более, любой проект со временем разрастается.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 10, 2016, 18:22 Я советую postgresql. Честно. Много лет использую его в продашене. Тем более, любой проект со временем разрастается. У меня стоит версия Qt 5.5Драйвер для postgreSQL нужно собирать или уже предустановлен как QSQLITE ? Название: Re: Работа в SQLite в многопоточном приложении Отправлено: sergek от Декабрь 10, 2016, 19:41 Драйвер для postgreSQL нужно собирать или уже предустановлен как QSQLITE ? Включен в установочный комплект. Если собираете из сорцов, нужно предварительно установить девелоперский пакет Postgres (типа libpq-dev).При работе с Postgres из разных потоков используйте в каждом потоке свое собственное подключение и все будет нормально. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Old от Декабрь 10, 2016, 19:50 Using SQLite In Multi-Threaded Applications (https://www.sqlite.org/threadsafe.html)
Но sqlite это не postgresql. Да. :) Название: Re: Работа в SQLite в многопоточном приложении Отправлено: kuzulis от Декабрь 10, 2016, 23:24 Цитировать С SQLite нельзя работать в несколько потоков Неужли? Вообще-то нужно просто создавать соединения в разных потоках.. Этого достаточно, ЕМНИП. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: panAlexey от Декабрь 10, 2016, 23:45 Я советую postgresql. Честно. Много лет использую его в продашене. Тем более, любой проект со временем разрастается. А как насчет Firebird или Линтер?Firebird для стандалоне или одноюзерских приложений по моему самое то что надо.. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Old от Декабрь 11, 2016, 07:34 А как насчет Firebird или Линтер? Линтер это postgresql, с дополнительными плюшками для разграничения доступа.Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 11, 2016, 09:34 Цитировать С SQLite нельзя работать в несколько потоков Неужли? Вообще-то нужно просто создавать соединения в разных потоках.. Этого достаточно, ЕМНИП. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 11, 2016, 09:35 Я советую postgresql. Честно. Много лет использую его в продашене. Тем более, любой проект со временем разрастается. А как насчет Firebird или Линтер?Firebird для стандалоне или одноюзерских приложений по моему самое то что надо.. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: kuzulis от Декабрь 11, 2016, 10:28 Цитировать Не поможет, ЕМНИП. Так же, как и доступ из нескольких процессов. Почему? У меня все работает... :) Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 11, 2016, 10:42 Значит либо сейчас стало можно, либо ты просто не попадал на 2 запроса изменения из разных потоков одновременно.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: kuzulis от Декабрь 11, 2016, 10:54 Цитировать Значит либо сейчас стало можно, либо ты просто не попадал на 2 запроса изменения из разных потоков одновременно. Не, SQLite разруливает все сам, т.к. по умолчанию он собирается с: SQLITE_THREADSAFE=1, который просто ставит запросы от разных потоков в очередь.. Типо они выполняются последовательно в итоге все-равно (как я понял), т.е. выигрыш только в том, что ГУЙ не тормозит. Цитировать SQLITE_THREADSAFE=<0 or 1 or 2> This option controls whether or not code is included in SQLite to enable it to operate safely in a multithreaded environment. The default is SQLITE_THREADSAFE=1 which is safe for use in a multithreaded environment. When compiled with SQLITE_THREADSAFE=0 all mutexing code is omitted and it is unsafe to use SQLite in a multithreaded program. When compiled with SQLITE_THREADSAFE=2, SQLite can be used in a multithreaded program so long as no two threads attempt to use the same database connection (or any prepared statements derived from that database connection) at the same time. To put it another way, SQLITE_THREADSAFE=1 sets the default threading mode to Serialized. SQLITE_THREADSAFE=2 sets the default threading mode to Multi-threaded. And SQLITE_THREADSAFE=0 sets the threading mode to Single-threaded. The value of SQLITE_THREADSAFE can be determined at run-time using the sqlite3_threadsafe() interface. When SQLite has been compiled with SQLITE_THREADSAFE=1 or SQLITE_THREADSAFE=2 then the threading mode can be altered at run-time using the sqlite3_config() interface together with one of these verbs: SQLITE_CONFIG_SINGLETHREAD SQLITE_CONFIG_MULTITHREAD SQLITE_CONFIG_SERIALIZED The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags to sqlite3_open_v2() can also be used to adjust the threading mode of individual database connections at run-time. Note that when SQLite is compiled with SQLITE_THREADSAFE=0, the code to make SQLite threadsafe is omitted from the build. When this occurs, it is impossible to change the threading mode at start-time or run-time. See the threading mode documentation for additional information on aspects of using SQLite in a multithreaded environment. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 11, 2016, 10:55 Цитировать С SQLite нельзя работать в несколько потоков Неужли? Вообще-то нужно просто создавать соединения в разных потоках.. Этого достаточно, ЕМНИП. Ниже приведу код простого приложения. Ошибка не вылетает сразу... нужно несколько раз запускать и закрывать приложение, и гдето 1 раз и трех или четырех попыток запуска приложения вылазит сообщения об ошибке. QObject::moveToThread: Current thread (0x6049a8) is not the object's thread (0x604970). Cannot move to target thread (0x5e4fa8) Я даже пытался понять на какой именно строке кода вылетает данная ошибка, как мне показалось после выполнения строки QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", this->nameConnect); ниже код mainwindow.h Код
mainwindow.cpp Код
database.h Код
database.cpp Код
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 11, 2016, 12:37 Сначала делай moveToThread, а потом уже конекты. У тебя коннекты с Direct соединились, а надо Queued
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Авварон от Декабрь 11, 2016, 12:49 Сначала делай moveToThread, а потом уже конекты. У тебя коннекты с Direct соединились, а надо Queued По умолчанию они авто, тип соединения определяется в момент эмита, а не коннекта. Дело не в этом. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 11, 2016, 13:11 Сначала делай moveToThread, а потом уже конекты. У тебя коннекты с Direct соединились, а надо Queued По умолчанию они авто, тип соединения определяется в момент эмита, а не коннекта. Дело не в этом. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Авварон от Декабрь 11, 2016, 13:19 А. Есть переменная окружения QT_FATAL_WARNINGS или как-то так, если ее поставить в 1 то программа упадет на этом ворнинге и можно будет получить стектрейс.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: kuzulis от Декабрь 11, 2016, 13:55 Цитировать Я попробывал делать соединение в разных потоках и это не помогло. Ниже приведу код простого приложения. Ошибка не вылетает сразу... нужно несколько раз запускать и закрывать приложение, и гдето 1 раз и трех или четырех попыток запуска приложения вылазит сообщения об ошибке. QObject::moveToThread: Current thread (0x6049a8) is not the object's thread (0x604970). Cannot move to target thread (0x5e4fa8) Так дело то в Вашем коде, а не в SQLite. :) Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 11, 2016, 14:02 Цитировать Я попробывал делать соединение в разных потоках и это не помогло. Ниже приведу код простого приложения. Ошибка не вылетает сразу... нужно несколько раз запускать и закрывать приложение, и гдето 1 раз и трех или четырех попыток запуска приложения вылазит сообщения об ошибке. QObject::moveToThread: Current thread (0x6049a8) is not the object's thread (0x604970). Cannot move to target thread (0x5e4fa8) Так дело то в Вашем коде, а не в SQLite. :) Буду раз если укажите на ошибку Название: Re: Работа в SQLite в многопоточном приложении Отправлено: kuzulis от Декабрь 11, 2016, 15:50 Для начала нужно вывести идентификаторы QThread::id из каждого метода и смотреть что не так.
Должно быть так, чтобы все методы/слоты класса DataBase выполнялись в контексте того треда в который этот объект перемещен. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: qate от Декабрь 12, 2016, 09:34 насколько я могу понять код, который лучше былобы выложить готовым проектом ибо лень его самому делать, метод инициализации БД будет вызван в GUI потоке,отя предполагалось в новом, см.
QObject::connect(thread, SIGNAL(started()), db, SLOT(ProcessFirst())); для выяснения кто кинул warning можно повесить свой обработчик qInstallMessageHandler и так точкой останова иметь полный стек Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 15:57 насколько я могу понять код, который лучше былобы выложить готовым проектом ибо лень его самому делать, метод инициализации БД будет вызван в GUI потоке,отя предполагалось в новом, см. GUI делает коннект, что как только запущен поток, то вызывается инициализация.QObject::connect(thread, SIGNAL(started()), db, SLOT(ProcessFirst())); для выяснения кто кинул warning можно повесить свой обработчик qInstallMessageHandler и так точкой останова иметь полный стек Инициализация БД происходит не в GUI а в дочернем потоке, и там же БД будет использоваться. Прикладываю готовый проект http://mamba.apibot.ru/tmp/sqlite.rar (http://mamba.apibot.ru/tmp/sqlite.rar) Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 16:11 У тебя пример некорректен, ты забыл db.open() сделать. Добавил - УМВР, никаких ворнингов.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 17:09 У тебя пример некорректен, ты забыл db.open() сделать. Добавил - УМВР, никаких ворнингов. все корректно.... db.open() даже не нужно вызывать,, ибо даже выполняя эту строку QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", this->nameConnect); уже будет ошибка. так что open не обязательно, ибо ошибка идет до open ЧТо такое - УМВР ??? Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 18:51 УМВР - У Меня Все Работает. С гуглом надо дружить, камрад. :)
Я собрал и запустил - ни одной ошибки в консоль не выдало. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 18:55 УМВР - У Меня Все Работает. С гуглом надо дружить, камрад. :) а запускали несколько раз? нужно раз 6 или 7.... она не сразу вылетаетЯ собрал и запустил - ни одной ошибки в консоль не выдало. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 19:00 Раз 10 подряд запустил. Ни одного вылета. Linux.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 19:01 Раз 10 подряд запустил. Ни одного вылета. Linux. а можете скинуть проект ваш сюда? Я у себя запущуНазвание: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 19:02 Я твой проект запускаю.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: panAlexey от Декабрь 12, 2016, 19:02 А как насчет Firebird или Линтер? Линтер это postgresql, с дополнительными плюшками для разграничения доступа.Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 19:21 Я твой проект запускаю. Странно.Я только что записал видео и загрузил на ютуб где у меня вылазит ошибка. https://www.youtube.com/watch?v=B0rrqNw2gxY (https://youtu.be/B0rrqNw2gxY) Может у нас сборки разные.... слышал что если собирать Qt из сорцов, то там можно выставлять режим работы SQLite Низнаю как у вас, я тупо скачивал инсталятор и устанавливал Qt 5.5 MSVC 2012 Название: Re: Работа в SQLite в многопоточном приложении Отправлено: panAlexey от Декабрь 12, 2016, 19:28 Есть пример asyncdb у Земскова.
https://yadi.sk/d/oNC_269533FSDb Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Авварон от Декабрь 12, 2016, 19:32 Вы стектрейс получили? Вам уже 2 способа сказали.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 19:55 Вы стектрейс получили? Вам уже 2 способа сказали. А как сделайть стектрейс?определить переменную QT_FATAL_WARNINGS ??? например так в файле main.cpp ? #define QT_FATAL_WARNINGS 1 Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 20:09 В настройках отладчика в Креаторе есть галочка останова при ворнингах.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 20:17 В настройках отладчика в Креаторе есть галочка останова при ворнингах. Пставил остановку на ворнингахтут останавливается QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", this->nameConnect); попробую покавыряю проект что выше дали.. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 20:20 А с одним тредом падает?
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 20:21 А с одним тредом падает? с одним тредом нету ворнинга...тока если 2 одновременно надо как то проверить в каком режиме SQLite http://www.sqlite.org/threadsafe.html 1) Single-thread. In this mode, all mutexes are disabled and SQLite is unsafe to use in more than a single thread at once. 2) Multi-thread. In this mode, SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or more threads. 3) Serialized. In serialized mode, SQLite can be safely used by multiple threads with no restriction. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 20:28 А попробуй статический мютекс объявить в методе DataBase::init и залочить его.
Код
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 20:35 А попробуй статический мютекс объявить в методе DataBase::init и залочить его. Код
так нету ворнинга.... хммм.... почему у вас без мьютекса нету ворнинга а у меня есть... черт разберешь, а вот с мьютексом все ок Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 20:38 Давай либо Вас, либо тебя. Второе предпочтительнее.
Походу, косяк при одновременном создании подключений из двух потоков. У меня нет ворнингов потому что Линух. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 20:42 Давай либо Вас, либо тебя. Второе предпочтительнее. ну а если я буду при инициализации использовать мьютекс, это же нормально? не страшно.? тормозов небудет думаюПоходу, косяк при одновременном создании подключений из двух потоков. У меня нет ворнингов потому что Линух. Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 20:43 Подключение к БД делается редко, поэтому не страшно.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 20:44 Подключение к БД делается редко, поэтому не страшно. Спасибо.... за помощь... у меня еще стоит mingwпопробую на нем еще тесты сделать Название: Re: Работа в SQLite в многопоточном приложении Отправлено: Пантер от Декабрь 12, 2016, 21:21 rudireg, совет тебе - на плоди потоки. Лучше заеб^Wзабабахай пул потоков к БД и рули через него. Приходит запрос, смотришь, есть ли свободный поток, если нету, создаешь новый, если есть, юзаешь первый свободный. Но только сначала убедись, что тебе это нужно, что один поток не справляется и ты упираешся в БД.
Название: Re: Работа в SQLite в многопоточном приложении Отправлено: rudireg от Декабрь 12, 2016, 21:52 rudireg, совет тебе - на плоди потоки. Лучше заеб^Wзабабахай пул потоков к БД и рули через него. Приходит запрос, смотришь, есть ли свободный поток, если нету, создаешь новый, если есть, юзаешь первый свободный. Но только сначала убедись, что тебе это нужно, что один поток не справляется и ты упираешся в БД. Ты прав... это оптимальный вариант... пул потоков это идея |