Core Data SQLite 存储在更新后变为只读
Posted
技术标签:
【中文标题】Core Data SQLite 存储在更新后变为只读【英文标题】:Core Data SQLite store becomes readonly after update 【发布时间】:2014-06-04 16:15:09 【问题描述】:我有报告说用户在通过 App Store 更新后无法使用 ios 应用程序,因为 Core Data 使用的 SQLite 数据库显然变成了只读的。这发生在保存在应用程序包的Documents
文件夹中的读/写持久存储中。
每个用户首次登录应用时,都会从头开始创建持久存储。其内容通过自定义渐进式托管对象模型迁移进行维护。碰巧的是,最新版本没有要执行的迁移,因此持久性存储应该在应用启动后就可以打开了。
我们从用户那里收到的错误是相同的,它发生在升级完成后启动过程的早期。 NSError
对象的 userInfo
就是我们在这种情况下捕获的:
NSSQLiteErrorDomain = 264;
NSUnderlyingException = "error during prepareSQL for SQL string 'SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA' : attempt to write a readonly database";
由于我们记录的内容和管理日志文件的方式存在一些缺陷,我无法准确知道在打开持久存储的过程中何时会发生这种情况。我们正在使用UIManagedDocument
,但没有通过 iCloud 共享任何文档。我假设错误是在打开现有文档包时发生的,但即使这是一个猜测。 (因此,我对未来版本的日志记录进行了改进。)
我最接近重现错误的方法是在 iOS 模拟器应用程序安装的文档包中的 persistentStore-shm
文件上使用文件权限 0444,然后使用 sqlite3
命令行尝试 SELECT
语句界面。这种情况下的错误是SQLITE_CANTOPEN
而不是SQLITE_READONLY
,所以我可能在关于文件权限的理论方面没有走上正轨。据我所知,UIManagedDocument
无论如何都会自动修复文件权限。
我想知道是否有人经历过类似的行为?如果是这样,有什么方法可以恢复,让用户不必经历重新创建本地数据存储的过程?
【问题讨论】:
您是否正在使用保存在捆绑包中的数据库? 是否有人已经在使用数据库(读写),而您尝试使用它(只读由于较早的读写)? @washloops 该数据库不包含在捆绑包中。它是在用户与应用交互并从服务器检索内容时构建的。 @JOM 据我所知,只有操作系统可以与数据库交互。我最早的怀疑是 App Store 升级过程可能是一个因素,但我想不出一种方法来证明这一点。 【参考方案1】:将您自己的描述符添加到选项中以(重新)启用历史跟踪...
在作为容器设置的一部分加载商店之前执行此操作:
let container = NSPersistentContainer(name: "YourDataStoreIdentifier" )
let description = container.persistentStoreDescriptions.first
// This allows a 'non-iCloud' sycning
// container to keep track of changes
// as if it was an iCloud syncing container
description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
container.loadPersistentStores(...
【讨论】:
这救了我。很高兴知道。【参考方案2】:我遇到了这个问题,这很令人费解。原来,预写日志的索引 -shm 文件已被清除,需要重建。这似乎是在将持久存储加载到 NSPersistentStoreCoordinator
时自动发生的。
如果你在这样做之前调用+[NSPersistentStore metadataForPersistentStoreWithURL:error:]
,我正在这样做,你会得到你报告的错误,返回值将是nil
。
因此,对我有用的解决方案是尝试检索元数据,如果失败并出现错误,则将持久性存储加载到 NSPersistentStoreCoordinator
以重建 -shm。之后,调用metadataForPersistentStoreWithURL:error:
将返回元数据而不会遇到只读错误。
【讨论】:
这真的很有趣。在打开商店之前有一种方法来检测是否需要重建 WAL 索引正是我所需要的。我会尽快调查这个程序。谢谢!以上是关于Core Data SQLite 存储在更新后变为只读的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Core Data SQLite 存储不能从 OS X 10.8 向后兼容到 10.4?
Core Data (SQLite) 手动迁移是事务性的吗?
在 NSLibraryDirectory 或 NSApplicationSupportDirectory 中存储 Core Data Sqlite?