备份 .sqlite(Core Data)

8
我有一个基于核心数据的应用程序,使用Dropbox备份和还原数据。我的备份方法很简单,我将用户的.sqlite文件复制到Dropbox上。目前,我的备份和还原功能都正常运行。但是我的问题出现在.sqlite文件本身。看起来这个文件不完整。我向应用程序中输入了大约125条记录并进行了备份。虽然备份出现在我的Dropbox中,但当我使用.sqlite浏览器工具查看内容时,我只能看到117条之前的记录。我尝试更新第一条记录,再次观察.sqlite文件,但仍然没有变化。更奇怪的是,应用程序似乎已经记录了所有的更改。当我添加新纪录或更新现有记录并重新启动应用程序时,新添加的数据似乎有保存下来。但是这些新添加的数据在我的.sqlite文件中却找不到。我正在使用以下代码进行备份:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSString *filePath = [[[appDelegate applicationDocumentsDirectory] path] stringByAppendingPathComponent:@"MyApp.sqlite"];


if (account) {
    if ([filesystem isShutDown]) {
        filesystem = [[DBFilesystem alloc] initWithAccount:account];
        [DBFilesystem setSharedFilesystem:filesystem];
    }

    DBPath *newPath = [[DBPath root] childPath:[NSString stringWithFormat:@"Backup - %@.sqlite", [NSDate date]]];
    DBFile *file = [[DBFilesystem sharedFilesystem] createFile:newPath error:nil];
    [file writeContentsOfFile:filePath shouldSteal:NO error:nil];
    [filesystem shutDown];

}

我也从模拟器文件夹中复制了.sqlite文件,并尝试在.sqlite浏览器中查看它。它仍然表现出相同的行为。有什么原因会发生这种情况吗?

1个回答

7
从iOS 7 / OS X 10.9开始,Core Data默认使用“写前日志”(WAL)作为底层SQLite存储文件的记录模式。在Technical Q&A QA1809: New default journaling mode for Core Data SQLite stores in iOS 7 and OS X Mavericks中有详细解释。
在WAL模式下,Core Data保持主要存储文件不变,并将事务追加到位于相同位置的-wal文件中。保存Core Data上下文后,-wal文件不会被删除,也不会将该文件中的数据合并到存储文件中。因此,仅复制存储文件可能会导致数据丢失和不一致。
这就解释了为什么仅有.sqlite文件是不完整的。作为解决方案,您可以执行以下操作(也在技术说明中说明):
  • Disable WAL-mode (and use the "old" rollback journaling mode) for the SQLite store by setting the

    @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
    

    option when adding the persistent store, or

  • Use the

    - (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error
    

    method to make a backup copy of the Core Data store.


那么你会推荐什么?苹果推荐您的第二种方法,但我不明白如何在Dropbox中使用它(它似乎是为iCloud量身定制的)。如果我现在禁用WAL模式,已输入的数据会丢失吗?您认为创建一个包含.sqlite文件和wal文件的zip文件并将其保存为备份(并执行相反操作以进行还原)怎么样? - Gaurav Wadhwani
@GauravWadhwani:在这个答案https://dev59.com/HWEi5IYBdhLWcg3wweqq#21002923中指出,使用journal_mode=DELETE打开存储不会销毁您的数据,但我自己没有测试过。使用第二种方法,您可能需要先备份到一个单独的(单文件)存储中,然后将其移动到Dropbox中(但我不熟悉Dropbox函数)。-很抱歉,我不能给您建议。也许另一个答案会来帮助更多。 - Martin R
谢谢你的回答。帮助我解决了我的问题 :) - Gaurav Wadhwani
@GauravWadhwani - 你能否请发布解决方案。我在使用migratePersistentStore时遇到了严重的问题。 - Jim Holland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接