从多个线程使用 QSqlQuery
Using QSqlQuery from multiple threads
我有很多 C++11 线程 运行ning,它们有时都需要访问数据库。在 main 中,我会初始化数据库连接并打开数据库。 Qt 文档说查询不是线程安全的,所以我使用全局互斥锁,直到 QSqlQuery 存在于线程内。
这有效,但是否保证有效,或者我 运行 有时会遇到问题?
您可以使用 SQL 函数编写 class 并使用 signals-slots 进行查询并从数据库中获取结果。
它是线程安全的,也不需要使用 mutex
。
你选择的方法不对。应该使用共享的 QSqlDatabase 对象而不是 QSqlQuery。请检查 next example 多线程数据库访问。如果您不清楚,请告诉我。会详细解释。
看看 Documentation 告诉我们,
A connection can only be used from within the thread that created it.
Moving connections between threads or creating queries from a
different thread is not supported.
所以你确实需要每个线程一个连接。我通过基于线程生成动态名称解决了这个问题:
auto name = "my_db_" + QString::number((quint64)QThread::currentThread(), 16);
if(QSqlDatabase::contains(name))
return QSqlDatabase::database(name);
else {
auto db = QSqlDatabase::addDatabase( "QSQLITE", name);
// open the database, setup tables, etc.
return db;
}
如果您使用不受 Qt 管理的线程,请使用 QThreadStorage
为每个线程生成名称:
// must be static, to be the same for all threads
static QThreadStorage<QString> storage;
QString name;
if(storage.hasLocalData())
name = storage.localData();
else {
//simple way to get a random name
name = "my_db_" + QUuid::createUuid().toString();
storage.setLocalData(name);
}
重要提示: Sqlite 可能会也可能不会处理多线程。参见 https://sqlite.org/threadsafe.html。据我所知,嵌入到 Qt 中的 sqlite 是线程安全的,这是默认设置,我在源代码中找不到任何禁用它的标志。但是,如果您使用的是不同的 sqlite 版本,请确保它确实支持线程。
我有很多 C++11 线程 运行ning,它们有时都需要访问数据库。在 main 中,我会初始化数据库连接并打开数据库。 Qt 文档说查询不是线程安全的,所以我使用全局互斥锁,直到 QSqlQuery 存在于线程内。
这有效,但是否保证有效,或者我 运行 有时会遇到问题?
您可以使用 SQL 函数编写 class 并使用 signals-slots 进行查询并从数据库中获取结果。
它是线程安全的,也不需要使用 mutex
。
你选择的方法不对。应该使用共享的 QSqlDatabase 对象而不是 QSqlQuery。请检查 next example 多线程数据库访问。如果您不清楚,请告诉我。会详细解释。
看看 Documentation 告诉我们,
A connection can only be used from within the thread that created it. Moving connections between threads or creating queries from a different thread is not supported.
所以你确实需要每个线程一个连接。我通过基于线程生成动态名称解决了这个问题:
auto name = "my_db_" + QString::number((quint64)QThread::currentThread(), 16);
if(QSqlDatabase::contains(name))
return QSqlDatabase::database(name);
else {
auto db = QSqlDatabase::addDatabase( "QSQLITE", name);
// open the database, setup tables, etc.
return db;
}
如果您使用不受 Qt 管理的线程,请使用 QThreadStorage
为每个线程生成名称:
// must be static, to be the same for all threads
static QThreadStorage<QString> storage;
QString name;
if(storage.hasLocalData())
name = storage.localData();
else {
//simple way to get a random name
name = "my_db_" + QUuid::createUuid().toString();
storage.setLocalData(name);
}
重要提示: Sqlite 可能会也可能不会处理多线程。参见 https://sqlite.org/threadsafe.html。据我所知,嵌入到 Qt 中的 sqlite 是线程安全的,这是默认设置,我在源代码中找不到任何禁用它的标志。但是,如果您使用的是不同的 sqlite 版本,请确保它确实支持线程。