• QT database连接问题


    在一个QT-Mysql的项目中,偶尔出现连接数据库很慢和连接失败的现象,查看后台能看到这样的警告

    Error in my_thread_global_end(): 1 threads didn't exit

    后来在qt论坛上看到类似的问题,提问者给出了以下代码,用100个线程同时连接数据再断开,果然能重现问题。

    class Client: public QRunnable
    {
    public:
        virtual void run();
    };
    void Client::run()
    {
        QString sID = QString::number((unsigned long long)QThread::currentThreadId());
        QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", sID); // unique connection name
    
        db.setHostName("localhost");
        db.setDatabaseName("test");
        db.setUserName("me");
        db.setPassword("mypass");
    
        db.open();
        // do something query...
        db.close(); // 对象并未释放,无法remove
        QSqlDatabase::removeDatabase(sID);
    }
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        QThreadPool pool;
        pool.setMaxThreadCount(100);
    
        for (int i = 0; i < 100; ++i)
        {
            Client *client = new Client;
            bool started = pool.tryStart(client);
            Q_ASSERT(started);
        }
        pool.waitForDone();
        return 0;
    }

    不过先出了另一个问题:removeDatabase: connection '**' is still in use, all queries will cease to work

    查了一下,原因是QSqlDatabase对象close()时连接并未完全释放,也就无法remove. 改成指针的形式可以解决  

        QSqlDatabase *pdb = new QSqlDatabase();
        *pdb = QSqlDatabase::addDatabase("QMYSQL", sID); // unique connection name
        pdb->set...;
        pdb->open();
        pdb->close();
        delete pdb; // 释放对象
        pdb = NULL;
        QSqlDatabase::removeDatabase(sID);

    解决这个之后,连接数据库很慢和失败、警告都出现了。经过反复尝试,发现QSqlDatabase::addDatabase/open不是线程安全的, 不能被打断,加锁保护后完全正常了。

    QMutex gMutexdb; // global mutex for db-open
        gMutexdb.Lock();
        *pdb = QSqlDatabase::addDatabase("QMYSQL", sID); // unique connection name
        pdb->set...;
        pdb->open();
        gMutexdb.Unlock();

    不过这种多数据库连接,应该做一个连接池来管理。

  • 相关阅读:
    对之前IoT项目的完善
    利用 esp8266 搭建简单物联网项目
    IOT(esp8266)
    ---分割线---
    百度云下载工具--雷鸟下载
    Win10安装Ubuntu子系统
    安装Ubuntu虚拟机
    搭建微信公众号后台(二)
    手把手教你基于CentOS8搭建微信订阅号后台服务(一)
    如何在PHP5中通过PDO连接SQLite3数据库
  • 原文地址:https://www.cnblogs.com/chaos77/p/6677024.html
Copyright © 2020-2023  润新知