在C ++中使用sqlite库时,sqlite3_stmt
上对SQLITE_BUSY
的调用可能会以多种不同方式失败。据我所知,除了一个之外,所有这些都应该导致异常,或者是由编程错误引起的。
SQLITE_BUSY
。我的意思是:sqlite3_step
只是意味着数据库被锁定,因为某些事务已经发生在它上面,对吗?假设某个不同的进程已经开始一个事务并且还没有提交或发布它,对SQLITE_BUSY
尝试编辑数据库或开始新事务的任何调用都将失败并显示sqlite3_step_or_block_until_available_then_step(my_stmt);
。
但是,这对我来说并不是一个错误:当使用资源时,我可以......等等!与互斥体(可能更复杂的性质)不同,我想,应该可以阻止当前线程/进程的执行,直到再次可以访问共享资源。
有没有办法做这样的事情?我想要的是形式:
SQLITE_BUSY
因此执行被阻止,直到数据库不再繁忙,我可以使用它。是否有sqlite库本身提供的解决方案?如果没有,我该怎么办?我的意思是,我显然可以忙着等到{{1}}错误不再返回,但它并没有真正意义,因为它消耗了大量资源。是否有更多表现方式来实现这一目标?
如果可能,请提供一些简短示例,以便我了解如何使其发挥作用!
答案 0 :(得分:1)
您可以使用互斥锁自行锁定数据库,但sqlite3执行provide a mechanism that might help(强调我的):
SQLITE_BUSY
SQLITE_BUSY结果代码表示由于某些其他数据库连接的并发活动(通常是单独进程中的数据库连接),无法写入(或在某些情况下读取)数据库文件。
例如,如果进程A处于大型写入事务的中间,同时进程B尝试启动新的写入事务,则进程B将返回SQLITE_BUSY结果,因为SQLite一次只支持一个编写器。在开始新事务之前,进程B需要等待进程A完成其事务。 处理B可以使用sqlite3_busy_handler()
和busy_timeout pragma
接口以及SQLITE_BUSY
来帮助它处理SQLITE_BUSY错误。
您可以register a callback to handle SQLITE_BUSY
,而不是返回std::mutex
的数据库,它将调用您的处理程序。您可以在链接中阅读这些限制。
我不会为此提供一个示例,因为我觉得解决having multiple threads access a database问题的可能性较小,因为每个数据库连接只能有一个繁忙的处理程序。
如果我怀疑来自your previous question,您可以控制访问数据库的所有代码,那么可能更容易使用std::conditional_variable
或{
std::lock_guard<std::mutex> lock(dbMutex);
sqlite3_stmt(...);
}
:
{{1}}