1

)

我正在使用我通过访问的 SQLite 数据库开发程序QSqlDatabase。我想处理(希望很少见)对数据库进行一些更改但不是由程序在运行时引起的情况(例如,用户可以删除写访问权限、移动或删除文件或手动修改它)。

我尝试使用QFileSystemWatcher. 我让它监视数据库文件,并且在所有向它写入内容的函数中,我阻止了它的信号,因此只有“外部”更改才会触发更改的信号。

问题是检查QFileSystemWatcher和/或实际写入磁盘的检查QSqlDatabase::commit()似乎并没有发生在我调用的确切时刻commit(),所以实际上,首先QFileSystemWatcher阻止 ' 的信号,然后我更改一些东西,然后我解除阻止它们并然后,它报告要更改的文件。

然后,我尝试在每次函数请求更改时设置一个布尔变量 ( m_writeInProgress) 。true“已更改”插槽然后检查是否已请求写入操作,如果是,则再次设置m_writeInProgressfalse并退出。这样,它只会处理“外部”更改。

问题仍然是,如果更改发生在实际写作正在进行的确切时刻,则不会被捕获。

所以可能,使用 aQFileSystemWatcher是实现这一点的错误方法。

这怎么能以安全的方式完成?

感谢大家的帮助!

编辑:

我找到了解决部分问题的方法。在数据库文件上启动排他锁可防止其他连接更改它。这很简单,我只需要执行

PRAGMA locking_mode = EXCLUSIVE
BEGIN EXCLUSIVE
COMMIT

并处理如果我的程序的另一个实例尝试访问数据库时出现的错误。

剩下的就是知道用户是否(不小心)在运行时删除了文件......

4

1 回答 1

0

首先,没有 SQLITE 支持:SQLITE 仅支持监视通过您直接控制的数据库连接创建的更改。无论在与您的流程同时发生的单独流程中发生什么,或者在您的流程未运行时发生的任何事情,都在设计上完全超出您的控制范围。

这个问题的典型解决方案是使用特定于您的应用程序(可能还有用户等)的密钥来加密数据库。然后,任何第三方进程都不能使用 SQLITE 修改数据库。当然,任何进程都可能损坏您的数据库,或者删除它——这太糟糕了。您可以通过使用加密签名轻松检测损坏,甚至可以使用纠错码,以便在发生一定程度的损坏时能够恢复数据。您不需要有人移动或删除数据库文件的通知:您将知道何时尝试打开数据库并且“找不到文件”错误会返回给您。

当然,以上所有都需要自定义VFS 实现。这对课程来说非常重要。

于 2018-05-31T21:11:00.340 回答