c++ - 判断 SQLite 数据库是否被锁定
问题描述
我已经阅读了有关如何检测 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)。并且回调函数也没有被调用。
我究竟做错了什么?
解决方案
正如文档中明确指出的那样,该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;
推荐阅读
- node.js - JWT - 使用 jsonwebtoken 的最佳方式是什么?我迷路了
- excel - VBA:方法的括号用法
- javascript - 当在 typed.js 上键入特定字符串时,有没有办法触发动画或类更改
- reactjs - 使用 Styled Components 更改 SVG 笔触的颜色
- amazon-web-services - 在 Amazon ECS 中将 POST 请求从一项服务发送到另一项服务
- c# - 如何从已登录用户处获取“B2C JWT 访问令牌”?
- websphere - JDBC 创建数据源需要重启 - Websphere 9.0
- python - Matplotlib:如何防止 Jupyter 将大图压缩到单个单元格中?
- javascript - 使用 console.log 上的 javascript 显示输出打印此表单中的数字
- ios - 如何从物品类别中获取物品