使用Qt在SQLite数据库上执行多线程操作时崩溃

时间:2016-06-10 06:26:09

标签: multithreading qt sqlite qtconcurrent

我有一个代码,可以对数据库执行3次异步生成操作。如果我运行3个异步操作,此代码会崩溃,但如果它只有一个没有问题。如何在SQLite上组织多线程操作?我尝试过QMutex.lock,但它没有用。

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtConcurrent/QtConcurrentRun>
#include <database.h>


int main(int argc, char *argv[])
{

QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
Database *db0=new Database();
Database *db1=new Database();
Database *db2=new Database();

QString param0="Select LastUpdateDate From TableLastUpdateLog Where TableName='T1'";
 QString param1="Select LastUpdateDate From TableLastUpdateLog Where TableName='T2'";
  QString param2="Select LastUpdateDate From TableLastUpdateLog Where TableName='T3'";


QtConcurrent::run(db0,&Database::Select,param0);
QtConcurrent::run(db1,&Database::Select,param1);
QtConcurrent::run(db2,&Database::Select,param2);



return app.exec();

}

database.cpp

void Database::Select(QString query) {

m_db=QSqlDatabase::addDatabase("QSQLITE","myconn");
m_db.setDatabaseName("./mytask.db");
bool result=m_db.open();
if(result==false)
    qDebug()<<"Failed";
else
{
    qDebug()<<"Connection is Success";
    m_qry=new QSqlQuery(m_db);
    m_qry->exec("PRAGMA foreign_keys = ON;");
    m_qry->exec("DSQLITE_THREADSAFE=2");
    m_qry->prepare(query);
    if(m_qry->exec()!=true)
    {
        qDebug()<<"Query Failed:"<<m_qry->lastError();
        qDebug()<<m_qry->lastQuery();
    }
    else
    {
        QSqlRecord rec=m_qry->record();
        while(m_qry->next())
        {
            qDebug()<<m_qry->value("LastUpdateDate").toDateTime();
        }

    }
}

m_db.close();
m_db.removeDatabase("myconn");

//mutex.unlock();   
}

1 个答案:

答案 0 :(得分:0)

您的代码崩溃是因为您仍然 使用相同的连接从每个线程访问数据库 。在Qt中,连接由它们的名称标识,即值“myconn”传递给addDatabase

不仅Qt行为不端,而且sqlite驱动程序也是如此。来自Qt docs

Warning: If you add a connection with the same name as an existing connection, 
the new connection replaces the old one. 

您的声明SQLITE_THREADSAFE=2允许多线程,只要no two threads attempt to use the same database connection,情况并非如此。

解决方案是为每个对象提供不同的连接名称。