c++ - 在多线程中创建 QSqlDatabase 连接时如何防止名称冲突
问题描述
我有多线程 QTcpServer 并且对于每个数据库请求,它都会创建新线程以保持服务器响应。所以在每个线程中我必须创建新的 QSqlDatabase 连接。但我不断收到连接之间的名称冲突。
这是我重新创建问题的示例代码。:-
#include <QSqlDatabase>
class DBTask
{
public:
DBTask(ClientSocket *socket,ConnectionWorker *connectionWorker);
~DBTask();
static void initStatic();
private:
static QThreadPool *pool; // all addConnection() call be be called in QtConcurrent::run with this pool
static QString host, user, type, password, name;
static quint64 dbConnectionNumber;
QSqlDatabase db;
ClientSocket *socket;
ConnectionWorker *connectionWorker;
bool addDatabase() ;
};
quint64 DBTask::dbConnectionNumber=0;
DBTask::DBTask(ClientSocket *socket, ConnectionWorker *connectionWorker):
socket(socket),
connectionWorker(connectionWorker)
{
dbConnectionNumber++;
}
bool DBTask::addDatabase() {
QSqlDatabase db = QSqlDatabase::addDatabase(type,QString::number(dbConnectionNumber));
db.setHostName(host);
db.setDatabaseName(name);
db.setUserName(user);
db.setPassword(password);
if(!db.open()){
qWarning() << "Error while opening database for socket " << socket << '\n' << db.lastError();
return false;
}
else {
return true;
}
}
当我以人类的速度手动检查我的应用程序时,这很好用但是当我运行一个模拟数千个请求的 c++ 测试代码时:-
void connectionTest(){
QThreadPool pool;
pool.setMaxThreadCount(10);
for(int i=0;i<10;i++){
QtConcurrent::run(&pool,[this](){
for(int i=0;i<1000;i++){
login(i%2); // login function sends request to QTcpServer
}
});
}
}
我收到多个这样的错误:-
QSqlDatabasePrivate::removeDatabase: connection '10' is still in use, all queries will cease to work.
QSqlDatabasePrivate::addDatabase: duplicate connection name '10', old connection removed.
QSqlDatabasePrivate::removeDatabase: connection '10' is still in use, all queries will cease to work.
QSqlDatabasePrivate::addDatabase: duplicate connection name '10', old connection removed.
和服务器因段错误而崩溃
解决方案
即使您使计数器原子化,一个线程仍然可以在DBTask::addDatabase
方法中被中断(在创建连接之前),另一个线程可以增加计数器,然后它们都继续并创建 2 个具有相同 ID 的连接。您需要在一个事务中进行这两项操作(增加计数器和DBTask::addDatabase
创建连接):在内部,通过使用互斥锁。
推荐阅读
- visual-studio-code - VS Code:替换内置变量launch.json中的字符
- python - 写入函数中的线程 Thread-10 错误,TypeError:write() 参数必须是 str,而不是字节
- android - 为什么 onLongclicklistener 在 kotlin 的 onBindviewholder 中不起作用
- python - 如何在没有 numpy 的情况下在 jit 装饰器上设置二维数组?
- php - 如何从 Symfony4 控制器获取“公共”目录
- angular - 注入的服务在函数中未定义但不是 ngInit
- android - 将动态视图添加到特定的 RecyclerView.Adapter
- c# - 没有为实体类型“XName”找到合适的构造函数
- entity-framework - “从‘System.Data.Entity.DynamicProxies’上的‘MyEntity’获取值时出错......”
- node.js - node-ipc 错误“消息很大,您可能需要考虑较小的消息。”