确定SQLite数据库是否被锁定

3
我已经阅读了其他关于如何检测SQLite数据库是否被锁定的答案,它建议使用sqlite3_busy_handler/sqlite3_busy_timeout。我正在使用支持SQLite数据库的Qt,但这在这里并不重要。
因为在我的应用程序使用情况中,另一个应用程序可能会访问同一个数据库,所以我需要处理这种情况。
以下是我打开数据库时设置的选项:
auto db = QSqlDatabase::database();
db.setDatabaseName(m_sDatabasePath);
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=0");
if (!db.open())
    return false;

我有一个函数,应该确定数据库是否被锁定:
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;
}

当数据库被锁定时,我执行此函数并打印出两个0(SQLITE_OK),而我期望得到5(SQLITE_BUSY)。并且回调函数也没有被调用。
我做错了什么?
1个回答

3

如文档中明确说明的那样,sqlite3_busy_handler函数为连接设置回调函数作为繁忙处理程序。每当遇到锁定时,可能会调用此类回调函数。在您的代码中,对sqlite3_busy_handler的调用返回SQLITE_OK,这是完全可以的:这意味着尝试设置回调成功,此时没有理由返回SQLITE_BUSY,因为该调用仅影响连接,而不影响数据库。

对于sqlite3_busy_timeout函数也是同样的情况,它设置了一种不同类型的繁忙处理程序(顺便替换了刚刚设置的回调),该程序只需睡眠指定的毫秒数,直到锁被释放。

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

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

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)
}

为了使锁无法获取时立即返回,请清除忙碌处理程序,为此连接设置繁忙超时为零(在打开它之前):
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=0");

为了测试这个功能,请在数据库上打开一个命令行sqlite3会话,并通过输入以下命令来锁定它:

sqlite> BEGIN EXCLUSIVE;

当您想释放锁时,只需输入:

sqlite> COMMIT;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接