我在10.6中编写了一个简单的Cocoa应用程序。我在程序运行时断电(程序定期保存到数据存储中),程序正在使用的sqlite文件已经以某种方式损坏。
我以标准方式创建托管对象上下文:
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
通常一切都很好,但这一次,在阅读一个对象时:
NSLog(@"%@",dir.files);
我明白了:
2011-06-03 11:33:38.079 Backup Check[1927:3c03] Relationship fault for
(<NSRelationshipDescription: 0x100562230>), name files, isOptional 1,
isTransient 0, entity Directory, renamingIdentifier files, validation
predicates (
), warnings (
), versionHashModifier (null), destination entity File, inverseRelationship
directory, minCount 0, maxCount 0 on 0x10058bbc0
我在命令行尝试了sqlite3工具,很多东西都可以正常读取,但是对于一些表读取,我得到了一堆表条目,然后:
SQL error: database disk image is malformed
我猜测电源故障恰好在保存期间发生。我有一些问题: 1)如何从中检测/恢复?现在,我没有收到任何在创建对象上下文时可以看到的错误。此外,许多表都没有错误,只有在深入研究子表时才会出现这种关系错误。我无法检查null,因为正在返回一个对象 - 它不是NSSet。这是一种关系错误对象。 2)我如何采取措施防止将来发生腐败?在创建托管对象上下文时是否有一种检查一致性的简单方法,如果检测到损坏,我可以回滚到旧版本?在App Support目录中,我只看到一个文件,即损坏的数据库。
答案 0 :(得分:3)
没有任何API工具可以修复损坏的SQL存储。这种情况非常罕见,没有多大意义。我在过去5年多看到了一个损坏的Core Data SQL存储。
从NSLog获取的打印输出不表示错误。使用“fault”一词并不意味着在这种情况下的错误,而是表明它是一个错误对象。错误是表示关系中的托管对象的轻量级“ghost”对象。故障用于维护对象图的完整性,而无需加载与每个对象关联的所有数据。 Fetches将默认返回关系错误,因此在关系中查看它们是正常的,并不表示错误。
SQL错误表明数据库的架构已损坏。没有自动解决方法。你只需要扼杀疯狂的低级SQL技能并将数据库重新组合在一起。这样做很难付出努力。 (首先,你必须弄清楚Apple的未记录的架构。)
最后,没有办法保护任何基于文件的持久性存储免受停电。如果写入硬件出现故障,即使是大铁块也会被破坏。 (这就是为什么服务器UPS系统是如此大的业务。)无论你做什么,在某些时候你都有硬件写入或发送数据,如果硬件在这一点下降,你在软件中无能为力。添加更多写入制作两份或更多份副本,只会增加更多的中断点。
这些类型的腐败非常罕见,我不打算尝试处理它们。但是,如果你是偏执狂,一个简单的部分解决方案是定期将商店文件复制到备份,这样至少你可以恢复到以前的版本,而不必从头开始。