Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/9: Рейтинг темы: голосов - 9, средняя оценка - 4.56
90 / 17 / 6
Регистрация: 21.09.2016
Сообщений: 176

QSQLITE и многопоточность

23.11.2019, 15:10. Показов 1895. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день! Возможно вопрос немного не в той секции форума, заранее извиняюсь.

Программа работает с sqlite. В эту БД планируется запись из разных потоков. И тут я немного задумался на счет того можно ли писать в разные таблицы одной БД не используя мутексы и семофоры?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.11.2019, 15:10
Ответы с готовыми решениями:

QSQLITE в многопоточной среде
Всем привет. Наткнулся на одну проблему которую не могу одолеть, провозился с ней 2 дня и так не работает. Суть проблемы в том что 2 потока...

QSQLITE driver и QNX
QSQLITE driver not loaded – ошибка на виртуальной машине с QNX. При запуске приложения Qt на ВМ в среде QNX через IDE Momentics...

QSQLITE driver not loaded
Проблема такая: все библиотеки на месте, даже программа их видит. Но не грузит. QSqldatabase: QSQLITE driver not loaded ...

4
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
23.11.2019, 16:15
Цитата Сообщение от RJM Посмотреть сообщение
Программа работает с sqlite.
Думаю, именно с SQLite такой фокус не пройдет. База же файловая, вряд ли получится работать с ней одновременно из нескольких потоков.
1
90 / 17 / 6
Регистрация: 21.09.2016
Сообщений: 176
23.11.2019, 16:22  [ТС]
insite2012, писать то можно в нее из разных потоков, только при этом надо мутексы и семофоры применить. Может такое ранее кто-то делал и я хочу уточнить можно ли создать на каждую таблицу БД свой мутекс (что значительно ускорит запись в БД если потоки хотят писать в разные таблицы) или же необходимо создавать один мутекс на всю БД (что значительно хуже) ?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
23.11.2019, 16:30
Цитата Сообщение от RJM Посмотреть сообщение
писать то можно в нее из разных потоков, только при этом надо мутексы и семофоры применить.
По сути, это то же самое, что я сказал выше, поскольку в реальности в каждый момент времени с ней будет работать только один поток.
Думаю, что все же придется
Цитата Сообщение от RJM Посмотреть сообщение
создавать один мутекс на всю БД
Хотя вы можете поэкспериментировать и рассказать результат, что у вас вышло.
1
90 / 17 / 6
Регистрация: 21.09.2016
Сообщений: 176
24.11.2019, 03:29  [ТС]
insite2012, собственно как вы и говорили - без мутекса никак. Код программы прилагаю, может кому пригодится...

Собственно без мутексов появляются проблемы в двух местах:

1) когда делаем query.prepare в потоке (база в этот момент может быть занята другим соединением и запрос на подготовку будет отвергнут, а значит в желаемую таблицу ничего не запишется)
2) когда делаем query.exec (тут просто могут быть потери некоторых данных)

.pro file
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
QT       += core gui sql
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
TARGET = untitled
TEMPLATE = app
 
 
SOURCES += main.cpp\
        widget.cpp \
    thread.cpp
 
HEADERS  += widget.h \
    thread.h
 
FORMS    += widget.ui
gui header

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QMutex>
#include <QDebug>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
    QMutex global_mute;
 
    bool init_db_connection();
    bool create_tabels(QSqlDatabase &db);
    void close_db_connection();
 
public slots:
    void create_dbs();
    void run_threaded_operation();
    void check_results();
 
private:
    Ui::Widget *ui;
    QString path;
    int incr;
};
 
#endif // WIDGET_H
gui cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "widget.h"
#include "ui_widget.h"
#include "thread.h"
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    path = "/tbd_test/test_connection.sqlite"; //here is your path to db file
    incr = 0;
    
    //binds for buttons
    connect(ui->create, SIGNAL(clicked(bool)), this, SLOT(create_dbs()));
    connect(ui->run, SIGNAL(clicked(bool)), this, SLOT(run_threaded_operation()));
}
 
Widget::~Widget()
{
    close_db_connection();
    delete ui;
}
 
bool Widget::init_db_connection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "test_connection");
    db.setDatabaseName(path);
    if(!db.open())
        return false;
    if(!create_tabels(db))
        return false;
    db.close();
    qDebug() << "DB created successfully";
    return true;
}
 
bool Widget::create_tabels(QSqlDatabase &db)
{
    QSqlQuery query(db);
    query.prepare("CREATE TABLE IF NOT EXISTS table_one (digital INTEGER)");
    if(!query.exec())
        return false;
 
    query.prepare("CREATE TABLE IF NOT EXISTS table_two (digital INTEGER)");
    if(!query.exec())
        return false;
 
    return true;
}
 
void Widget::close_db_connection()
{
    QSqlDatabase::removeDatabase("test_connection");
}
 
void Widget::create_dbs()
{
    if(!init_db_connection())
        qDebug() << "Failed to create db";
    close_db_connection();
}
 
void Widget::run_threaded_operation()
{
    ui->create->setEnabled(false);
    ui->run->setEnabled(false);
 
    //create first thread
    Thread *th1 = new Thread(path, true, &global_mute);
    connect(th1, SIGNAL(finished()), th1, SLOT(destroy_thread()));
    connect(th1, SIGNAL(finished()), this, SLOT(check_results()));
 
    //create second thread
    Thread *th2 = new Thread(path, false, &global_mute);
    connect(th2, SIGNAL(finished()), th2, SLOT(destroy_thread()));
    connect(th2, SIGNAL(finished()), this, SLOT(check_results()));
 
    //run threaded operations
    th1->start();
    th2->start();
}
 
void Widget::check_results()
{
    incr++;
    if(incr == 2)
    {
        incr = 0;
 
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "test_connection");
        db.setDatabaseName(path);
        db.open();
 
        QSqlQuery query(db);
        query.prepare("SELECT COUNT (digital) FROM table_one");
        query.exec();
        while(query.next())
            qDebug() << "First table contains" << query.value(0).toInt() << "records";
 
        query.prepare("SELECT COUNT (digital) FROM table_two");
        query.exec();
        while(query.next())
            qDebug() << "Second table contains" << query.value(0).toInt() << "records";
        db.close();
        close();
    }
}
thread header

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef THREAD_H
#define THREAD_H
 
#include <QObject>
#include <QThread>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QMutex>
#include <QDebug>
 
class Thread : public QThread
{
    Q_OBJECT
public:
    explicit Thread(QString &pt, bool ift, QMutex *mute, QObject *parent = 0);
    void close_db_connection();
 
protected:
    void run();
 
public slots:
    void destroy_thread();
 
private:
    QString path;
    bool is_first_table;
    QMutex *global_mutex;
};
 
#endif // THREAD_H
thread cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "thread.h"
 
Thread::Thread(QString &pt, bool ift, QMutex *mute, QObject *parent) : QThread(parent)
{
    path = pt;
    is_first_table = ift;
    global_mutex = mute;
}
 
void Thread::close_db_connection()
{
    if(is_first_table)
        QSqlDatabase::removeDatabase("first_table");
    else
        QSqlDatabase::removeDatabase("second_table");
}
 
void Thread::run()
{
    qDebug() << this << "started" << is_first_table;
 
    QSqlDatabase db;
 
    if(is_first_table)
        db = QSqlDatabase::addDatabase("QSQLITE", "first_table");
    else
        db = QSqlDatabase::addDatabase("QSQLITE", "second_table");
    db.setDatabaseName(path);
    db.open();
 
    QSqlQuery query(db);
    if(is_first_table)
    {
        global_mutex->lock();
        if(!query.prepare("INSERT INTO table_one (digital) VALUES (:digital)"))
            qDebug() << "failed make prepare" << is_first_table << query.lastError().text();
        global_mutex->unlock();
    }
    else
    {
        global_mutex->lock();
        if(!query.prepare("INSERT INTO table_two (digital) VALUES (:digital)"))
            qDebug() << "failed make prepare" << is_first_table << query.lastError().text();
        global_mutex->unlock();
    }
 
    for(int i = 0; i < 500; i++)
    {
        global_mutex->lock();
        query.bindValue(":mval", i);
        if(!query.exec())
            qDebug() << "failed query" << is_first_table << query.lastError().text();
        global_mutex->unlock();
        qDebug() << this << i;
    }
 
    db.close();
}
 
void Thread::destroy_thread()
{
    qDebug() << this << "work completed" << is_first_table;
    close_db_connection();
    deleteLater();
}
main

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
#include "widget.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
    return a.exec();
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
24.11.2019, 03:29
Помогаю со студенческими работами здесь

QSQLite Сортировка базы данных
Привет всем.Пишу программку на Qt и использую SQLite. Надо что бы в базе данные были отсортированы. Использовал ORDER BY ASC,но тут вышла...

Ошибка QSQLITE driver not loaded
При переносе проги на другой комп со всеми dll в папке, прога запускается нормально, но получаю exception - QSQLITE driver not loaded. an...

Установка драйверов QPSQL, QSQLite
Здравствуйте, помогите разобраться, целый день бъюсь( Подскажите, как подключать эти драйвера и какой мне нужен, если я пользуюсь...

Не происходит подключение с базой QSQLITE
Здравствуйте, помогите разобраться в чем ошибка, не происходит подключение с базой QSQLITE Основное же тип и имя базы прописаны, ...

На машине клиента "QSQLITE" выдает: Driver not loaded Driver not loaded
#include &lt;QSqlDatabase&gt; #include &lt;QSqlQuery&gt; #include &lt;QSqlRecord&gt; #include &lt;QSqlError&gt; #include &lt;QDebug&gt; #include &lt;QFileDialog&gt; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. На мобильном - сканируйте QR-код. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru