为什么我的QSqlDatabase :: open()卡住了?

时间:2013-12-21 08:50:07

标签: c++ mysql qt

我试图在某种程度上建立一个MySQL连接池。用例是这样的:

当我从它请求连接时(QSqlDatabase对象),它将基于当前线程id生成一个连接名称作为字符串。如果我已经拥有该名称的开放连接,它将返回该名称。否则,它将打开与该名称的连接,它将返回它。

我还保留一个标志,指示连接是否已被使用以及上次使用的时间戳。我还有一个QTimer,它会定期打勾并关闭未使用但未在指定时间内使用的连接。

我认为实施很好。但是,每隔一段时间我的getConnection()就会卡住。这是来自gdb的堆栈跟踪。当发生这种情况时,程序不会崩溃或类似的事情,但getConnection()不会返回。

#0  pthread_once () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:94
#1  0x00007f1fae288199 in get_charset_by_csname () from /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18
#2  0x00007f1fae271a97 in mysql_init_character_set () from /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18
#3  0x00007f1fae272960 in mysql_real_connect () from /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18
#4  0x00007f1fae77c0ad in ?? () from /usr/local/Qt-5.2.0/plugins/sqldrivers/libqsqlmysql.so
#5  0x00007f1fb5bd0251 in QSqlDatabase::open() () from /usr/local/Qt-5.2.0/lib/libQt5Sql.so.5
#6  0x00007f1fb895b479 in ConnectionPool::getConnection(QString const&) () from /home/user/demo1/lib/libMySqlConn.so

以下是我的代码片段:

// Members of ConnectionPool:
// QMutex mMutex
// QHash<QString, ConnectionData> mConnections;

struct ConnectionData
{
    QSqlDatabase* pDatabase;
    QDateTime     lastUsed;
    int           refCount = 0;
};

QString ConnectionPool::getConnectionName()
{
    const quint64 tid = *reinterpret_cast<const quint64 *>(QThread::currentThreadId());
    return QString("%1").arg(tid, 12, 16, '0');
}

QSqlDatabase* ConnectionPool::getConnection(const QString& connName)
{
    QSqlDatabase* pDatabase = new QSqlDatabase(QSqlDatabase::addDatabase("QMYSQL", connName));
    pDatabase->setHostName("localhost");
    pDatabase->setPort(3306);
    pDatabase->setDatabaseName("test1");
    pDatabase->setUserName("user");
    pDatabase->setPassword("pass");
    pDatabase->setConnectOptions("MYSQL_OPT_RECONNECT=1");

    if (!pDatabase->open())
    {
        delete pDatabase;
        pDatabase = nullptr;
        QSqlDatabase::removeDatabase(connName);
    }

    return pDatabase;
}

bool ConnectionPool::connection(QSqlDatabase& db)
{
    const QString connName = getConnectionName();
    QMutexLocker locker(&mMutex);

    if (mConnections.contains(connName))
    {
        ConnectionData& conndata = mConnections[connName];
        if (conndata.pDatabase->isOpen())
        {
            db = *conndata.pDatabase;
            conndata.refCount++;
            conndata.lastUsed = QDateTime::currentDateTime();
            return true;
        }
        delete conndata.pDatabase;
        mConnections.remove(connName);
        QSqlDatabase::removeDatabase(connName);
    }

    QSqlDatabase* pDatabase = getConnection(connName);

    if (!pDatabase)
        return false;

    ConnectionData conndata;
    conndata.refCount  = 1;
    conndata.pDatabase = pDatabase;
    conndata.lastUsed  = QDateTime::currentDateTime();
    mConnections.insert(connName, conndata);

    db = *pDatabase;
    return true;
}

0 个答案:

没有答案