开发者

Core Data corruption in an sqlite store after a power failure

I am writing a simple Cocoa application in 10.6. I had a power outage while the program was running (the program periodically saves to a data store), and the sqlite file that my program is using has become corrupted in some way.

I create the managed object context in a standard way:

managedObjectContext = [[NSManagedObjectContext alloc] 开发者_开发技巧init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];

and normally everything is fine, but this time, when reading an object:

NSLog(@"%@",dir.files);

I get:

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

I tried the sqlite3 tool at the command line, and many things can be read properly, but for some table reads I get a bunch of table entries, and then:

SQL error: database disk image is malformed

I'm guessing that the power failure occurred exactly during saving. I have a couple of questions: 1) How can I detect/recover from this? Right now I'm not getting any errors that I can see when the object context is created. Also, many of the tables are without errors, and only when delving into the subtables am I getting this relationship fault. I can't check against null, because an object is being returned - it's just not the NSSet. It's some kind of relationship fault object. 2) How can I take steps to prevent corruption in the future? Is there an easy way to check for consistency when creating the managed object context, and if corruption is detected I can roll back to an old version? In the App Support directory I only see one file, which is the corrupted database.


There aren't any API tools to repair a corrupted SQL store. It simply so rare an occurrence that there's not much point. I've seen exactly one corrupted Core Data SQL store in last 5+ years.

The print out you are getting from the NSLog does not indicate an error. The use of the word "fault" doesn't mean error in this context but rather indicates it is a fault object. Faults are lightweight "ghost" objects that represent managed objects in a relationship Faults are used to maintain the object graph integrity without having to load in the all the data associated with each object. Fetches will return relationship faults by default so seeing them in a relationship is normal and does not indicate an error.

The SQL error indicates that schema for the db has been corrupted. There is no automated way to fix that. You just have to whip out your mad, low-level SQL skills and stitch the db back together. It is rarely worth the effort to do so. (For one thing, you have to puzzle out Apple's undocumented schema.)

Lastly, there is no way to protect any file-based persistence storage from a power outage. Even big iron dbs can be trashed if the writing hardware goes down. (That is why server UPS system are such a big business.) No matter what you do, at some point you have the hardware writing or sending data and if the hardware goes down at that point there is nothing you can do in software. Adding more writes e.g. making two or more copies, just adds more points of interruption.

These types of corruption are so rare that I wouldn't bother trying to deal with them. However, if you're paranoid, a simple partial solution would be to copy the store file periodically to a backup so that at least you could revert to previous version and not have to start over from scratch.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜