首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >确定SQLite数据库是否已锁定

确定SQLite数据库是否已锁定
EN

Stack Overflow用户
提问于 2019-09-01 08:47:52
回答 1查看 2K关注 0票数 2

我读过关于如何检测SQLite数据库是否被锁定的其他答案,它建议使用sqlite3_busy_handler/sqlite3_busy_timeout。我使用的是Qt,它支持SQLite数据库,但这在这里并不重要。

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

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

代码语言:javascript
复制
auto db = QSqlDatabase::database();
db.setDatabaseName(m_sDatabasePath);
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=0");
if (!db.open())
    return false;

我有一个函数,它应该确定数据库是否被锁定:

代码语言:javascript
复制
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 (好的),而我希望得到5 (忙着)。回调函数也不会被调用。

我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-04 10:38:18

正如文档中明确指出的那样,sqlite3_busy_handler函数将回调函数设置为连接的繁忙处理程序。每当遇到锁时,就可能调用这种回调。在您的代码中,对sqlite3_busy_handler的调用返回SQLITE_OK,这很好:这意味着尝试设置回调成功,此时没有理由返回SQLITE_BUSY,因为调用只影响连接,而不是数据库。

sqlite3_busy_timeout函数也是如此,它反过来设置了一种不同类型的繁忙处理程序(顺便说一句,它替换了刚才设置的回调),它只是在释放锁之前睡上指定的毫秒。

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

所以你可以使用这样的函数:

代码语言:javascript
复制
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)
}

若要使其在无法获取锁时立即返回,请清除繁忙处理程序,将此连接的繁忙超时设置为零(在打开它之前):

代码语言:javascript
复制
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=0");

要测试该函数,请在数据库上打开命令行sqlite3会话,并通过键入以下命令来锁定它:

代码语言:javascript
复制
sqlite> BEGIN EXCLUSIVE;

当您想要释放锁时,只需键入

代码语言:javascript
复制
sqlite> COMMIT;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57744538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档