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();

不過這種多數據庫連接,應該做一個連接池來管理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM