qt在不同线程中同时进行MySQL查询=崩溃
qt simultaneous MySQL queries in different threads = crash
我有一个用C++编写的多线程Qt5应用程序,其中每个线程都在向同一数据库写入。
我在多个线程之间共享相同的数据库QSqlDatabase变量,但每个线程都创建自己的查询。我经常遇到崩溃,我在崩溃时捕捉到了以下信息:
Driver error [QMYSQL3: Unable to store statement results]
Database error [Commands out of sync; you can't run this command now]
Type [2]
Number [2014]
首先,我可以在多个线程中同时进行MySQL查询吗?如果是,我是否需要使用互斥锁来保护SQL调用?还是我需要发布更多信息。。。。
更新:我有一个单独的DBManager线程,它处理打开/关闭数据库和简单的数据库写入。我这样做是因为我的数据库经常离线,而且我不希望其他线程在数据库打开失败时挂起长达2分钟。不,我有更多的线程来做报告,并且必须从数据库中检索大量的数据。
如下所述,不允许跨线程共享数据库句柄。所以现在也许这更多的是一个设计问题——处理这种情况的最佳方法是什么?我不希望每个访问数据库的线程都尝试自己打开并等待2分钟,以防数据库离线
阅读SQL模块的文档,特别是线程部分,其中指出每个连接只能在创建它的线程中使用。
因此,添加互斥对象还不够好,您必须在每个线程中创建一个新的连接对象,或者将所需的数据传递给执行所有DB查询的专用线程。
我通常通过在数据库管理器类上提供一个工厂方法来处理这个问题,这个方法看起来类似于(半伪代码):
static QHash<QThread, QSqlDatabase> DatabaseManager::s_instances;
static QMutex DatabaseManager::s_databaseMutex;
QSqlDatabase DatabaseManager::database() {
QMutexLocker locker(s_databaseMutex);
QThread *thread = QThread::currentThread();
// if we have a connection for this thread, return it
if (s_instances.contains(thread))
return s_instances[thread];
}
// otherwise, create a new connection for this thread
QSqlDatabase connection =
QSqlDatabase::cloneDatabase(existingConnection, uniqueNameForNewInstanceOnThisThread);
// open the database connection
// initialize the database connection
s_instances.insert(thread, connection);
return connection;
}
只要您确保创建了一个初始连接(您可以修改工厂以包含该连接,或者只在DatabaseManager构造函数中创建初始连接),您就应该能够将使用QSqlDatabase的大多数现有情况替换为:
QSqlQuery query(DatabaseManager::database());
query.exec(<some sql>);
不用担心你从哪个线程调用。希望能有所帮助!
这只是mbroadst的一个很好的答案,只做了一些小改动。此代码应完整且可直接编译:
database_manager.h:
#ifndef DATABASEMANAGER_H
#define DATABASEMANAGER_H
#include <QMutex>
#include <QHash>
#include <QSqlDatabase>
class QThread;
class DatabaseManager
{
public:
static QSqlDatabase database(const QString& connectionName = QLatin1String(QSqlDatabase::defaultConnection));
private:
static QMutex s_databaseMutex;
static QHash<QThread*, QSqlDatabase> s_instances;
};
#endif // DATABASEMANAGER_H
database_manager.cpp:
#include "database_manager.h"
#include <QSqlDatabase>
#include <QMutexLocker>
#include <QThread>
#include <stdexcept>
QMutex DatabaseManager::s_databaseMutex;
QHash<QThread*, QHash<QString, QSqlDatabase>> DatabaseManager::s_instances;
QSqlDatabase DatabaseManager::database(const QString& connectionName)
{
QMutexLocker locker(&s_databaseMutex);
QThread *thread = QThread::currentThread();
// if we have a connection for this thread, return it
auto it_thread = s_instances.find(thread);
if (it_thread != s_instances.end()) {
auto it_conn = it_thread.value().find(connectionName);
if (it_conn != it_thread.value().end()) {
return it_conn.value();
}
}
// otherwise, create a new connection for this thread
QSqlDatabase connection = QSqlDatabase::cloneDatabase(
QSqlDatabase::database(connectionName),
QString("%1_%2").arg(connectionName).arg((int)thread));
// open the database connection
// initialize the database connection
if (!connection.open()) {
throw std::runtime_error("Unable to open the new database connection.");
}
s_instances[thread][connectionName] = connection;
return connection;
}
用法:使用DatabaseManager::database()而不是QSqlDatabase::database()
编辑于2016-07-01:修复了多个连接名称的错误
- MySQL c++ 连接器:使用 SetBlob() 在查询中设置多个 blob 数据的正确方法是什么?
- 如何使用C++检查 mysql 查询是否成功
- 在 MySQL 连接器C++ API 中使用一个函数调用执行多个查询的正确方法是什么?
- 如何正确编写 mysql 查询
- 如何在QT中进行MySQL查询
- Mysql 查询错误
- 使用 Qt 从 mysql 查询构造 2D 向量
- 我可以在mysql查询中调用一个函数吗
- MySQL C++查询访问违规
- 如何用c++和mysql发送动态的mysql查询
- c++ Mysql查询ascii格式
- c++中的动态mysql查询
- 如何在mysql查询后获得原始数据
- Mysql查询字符串在查询c++中不工作
- 如何使用本地变量作为MySQL查询的一部分(Qt c++)
- 使用c++在Mysql查询中插入JSON格式
- Mysql ++查询失败
- 检测服务器过载以限制mysql查询
- 向MySQL++查询添加字符串
- qt在不同线程中同时进行MySQL查询=崩溃