)
我正在使用我通过QSqlDatabase
访问的SQLite数据库来开发一个程序。我想处理(希望很少见)对数据库进行一些更改的情况,这些更改不是程序在运行时引起的(例如,用户可以删除写访问,移动或删除文件或手动修改它)。
我尝试使用QFileSystemWatcher
。我让它观察数据库文件,在所有函数中,我阻止了它的信号,这样只有“外部”的变化才能触发改变的信号。
问题是QFileSystemWatcher
和/或QSqlDatabase::commit()
的实际写入磁盘的检查似乎不会在我调用commit()
的那一刻发生,所以实际上,首先QFileSystemWatcher
的信号被阻止,然后我更改了一些东西,然后我取消阻止它们然后报告要更改的文件。
每次函数请求更改时,我都会尝试将bool变量(m_writeInProgress
)设置为true
。然后,“已更改”的插槽会检查是否已请求写入操作,如果是,请再次将m_writeInProgress
设置为false
并退出。这样,它只会处理“外部”变化。
问题仍然存在,如果在实际写作的确切时刻发生了变化,那么它就不会被捕获。
因此,使用QFileSystemWatcher
是实现此目的的错误方法。
怎样才能以安全的方式完成?
感谢您的帮助!
修改
我找到了解决部分问题的方法。在数据库文件上启动独占锁可防止其他连接更改它。这很简单,我只需要执行
PRAGMA locking_mode = EXCLUSIVE
BEGIN EXCLUSIVE
COMMIT
并处理在程序的另一个实例尝试访问数据库时出现的错误。
剩下的就是知道用户(意外地)是否在运行时删除了文件......
答案 0 :(得分:0)
首先,没有SQLITE支持:SQLITE仅支持监视通过直接控制中的数据库连接创建的更改。无论在与您的流程同时进行的单独流程中发生什么,或者您的流程未运行,设计都完全不受您的控制。
此问题的规范解决方案是使用特定于您的应用程序的密钥(可能还有用户等)加密数据库。然后,没有第三方进程可以使用SQLITE修改数据库。当然,任何进程都可能破坏您的数据库,或者摆脱它 - 这太糟糕了。您可以通过使用加密签名,甚至纠错代码来轻松检测损坏,以便在发生一定程度的损坏时能够恢复数据。您不需要有人移动或删除数据库文件的通知:您将知道何时尝试打开数据库并且“找不到文件”错误会返回给您。
当然,以上所有内容都需要自定义VFS implementation。这对于课程来说非常平等。