C++ 确定SQLite数据库是否已锁定

C++ 确定SQLite数据库是否已锁定,c++,database,sqlite,qt,locking,C++,Database,Sqlite,Qt,Locking,我已经阅读了关于如何检测SQLite数据库是否被锁定的其他答案,建议使用sqlite3\u busy\u处理程序/sqlite3\u busy\u timeout。我使用的是Qt,它支持SQLite数据库,但这在这里并不重要 因为在我的应用程序的用例中,另一个应用程序可能访问同一个数据库,所以我需要处理这种情况 以下是我在打开数据库时设置的选项: auto db = QSqlDatabase::database(); db.setDatabaseName(m_sDatabasePath); db

我已经阅读了关于如何检测SQLite数据库是否被锁定的其他答案,建议使用
sqlite3\u busy\u处理程序
/
sqlite3\u busy\u timeout
。我使用的是Qt,它支持SQLite数据库,但这在这里并不重要

因为在我的应用程序的用例中,另一个应用程序可能访问同一个数据库,所以我需要处理这种情况

以下是我在打开数据库时设置的选项:

auto db = QSqlDatabase::database();
db.setDatabaseName(m_sDatabasePath);
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=0");
if (!db.open())
    return false;
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=0");
我有一个函数可以确定数据库是否被锁定:

int callback(void *data, int)
{
    std::cout << "callback" << std::endl;
    return 0;
}

bool isDatabaseLocked(const QSqlDatabase &db)
{
    if (auto driver = db.driver())
    {
        // get driver handler
        QVariant v = driver->handle();
        if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0)
        {
            // v.data() returns a pointer to the handle
            auto handle = *static_cast<sqlite3 **>(v.data());
            if (handle)
            {
                std::cout << sqlite3_busy_handler(handle, callback, nullptr) << std::endl;
                std::cout << sqlite3_busy_timeout(handle, 0) << std::endl;
            }
        }
    }

    return true;
}
int回调(void*data,int)
{

std::cout正如文档中明确指出的那样,
sqlite3\u busy\u处理程序
函数将回调函数设置为连接的繁忙处理程序。只要遇到锁,就可以调用此类回调。在代码中,调用
sqlite3\u busy\u处理程序
返回
SQLITE\u OK
,这很好:它意味着尝试设置回调成功,此时没有理由返回
SQLITE\u BUSY
,因为调用只影响连接,而不影响数据库

差不多同样的情况也适用于
sqlite3\u busy\u timeout
函数,该函数反过来设置一种不同类型的busy处理程序(顺便说一下,它取代了刚才设置的回调),该处理程序只需休眠指定的毫秒数,直到释放锁为止

现在,一般来说,如何检测资源是否被锁定?通常的方法是:尝试锁定它

因此,您可以使用如下函数:

bool isDatabaseLocked(const QSqlDatabase & db)
{
    QSqlQuery q(db);
    if(q.exec("BEGIN EXCLUSIVE")) //tries to acquire the lock
    {
        q.exec("COMMIT"); //releases the lock immediately
        return false; //db is not locked
    }
    return true; //failed to acquire the lock: returns true (db is locked)
}
要使其在无法获取锁时立即返回,请清除忙处理程序,将此连接的忙超时设置为零(在打开之前):

要测试该功能,请在数据库上打开命令行
sqlite3
会话,然后键入以下内容锁定该会话:

sqlite> BEGIN EXCLUSIVE;
当您想释放锁时,只需键入

sqlite> COMMIT;