【发布时间】:2023-03-19 05:28:01
【问题描述】:
我最近修改了我的 iOS 应用程序,为使用 SQLCipher 加密的数据库和非加密数据库(也是 SQLite)启用序列化模式。我还为每个数据库维护一个静态 sqlite3 连接,每个数据库只打开一次(通过简单地检查空值)并在应用程序的整个生命周期内共享。
该应用程序需要具有类似同步的行为,该行为将使用肥皂请求定期从远程数据库下载大量记录并更新本地加密数据库的内容。当然,使用该应用程序的人可能会或可能不会更新或读取数据库,这取决于他们在做什么,因此我进行了上一段中提到的更改。
在进行短期测试时,事情的运作方式似乎没有任何问题,而且我还没有遇到任何问题。
但是,一些用户报告说他们无法访问加密数据库,我正试图找出原因。
我的想法如下:另一个开发人员编写的方法声明所有 sqlite3_stmt 都是静态的(我相信这段代码在有问题的版本中)。过去,当使用特定方法的两个线程同时运行时,我注意到崩溃。一个线程在另一个线程使用它时完成、修改或替换 sqlite3_stmt。崩溃并不总是发生,因为他将大部分 SQLite 代码包装在 try/catch 块中。如果 SQLite 确实使用 prepare 和 finalize 来实现锁定,那么在这种情况下由于它们的静态性质而发生的 sqlite3_stmt 的孤立是否会使数据库进入不可操作状态?例如,当一条语句在被单步执行后获得排他锁时,被另一个线程中运行的同一方法中的赋值替换?
我意识到这并不一定意味着数据库将永久不可用,但是,考虑一下这种情况:
在应用程序生命周期的某个时间点,它会重新设置加密数据库的密钥,并且该密钥存储在另一个数据库中。假设它成功地重新加密了加密的数据库,但是由于我上面提到的原因,新的密钥没有存储在另一个数据库中。 假设数据库在某个时候没有损坏(我并不是真的指望这种情况),这是我能想出的唯一解释为什么用户可能无法在之后使用加密数据库重新启动 iOS 应用程序,因为该应用程序将是唯一访问数据库文件的应用程序。
由于我无法重现此问题,我只能推测可能的原因。你有什么想法?对于很少发生的事情,这似乎是一个合理的场景吗?您还有其他想法可以研究吗?
【问题讨论】:
标签: ios objective-c sqlite concurrency sqlcipher