如果不关闭sqlite数据库是否可能丢失数据?
如果在 iOS/iPhone 中 SQLite 数据库未正确关闭,是否可能会丢失数据?
我正在考虑在 applicationWillTerminate
中关闭数据库,但首先要确保这不会产生任何令人讨厌的副作用。
Is it possible to lose data if a SQLite DB is not closed properly in iOS/iPhone?
I was thinking of closing the DB in applicationWillTerminate
, but want to make sure this doesn't have any nasty side-effects first.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
大多数情况下,不会; sqlite3 在返回之前将所有内容写入“磁盘”(并根据需要调用 fflush/fsync/等)。
有一个很大的例外:如果关闭数据库时存在未提交的事务,那么下次打开数据库时它将回滚。
到底会发生什么取决于 PRAGMA Journal_mode:如果它是“内存”或“关闭”,则如果您的应用程序在写入过程中崩溃,数据库可能会损坏。我认为PRAGMAlocking_mode仅影响释放锁时发生的情况,而不是交易完整性。
请注意,-applicationWillTerminate: 无论如何都不够! 如果您尚未设置 UIApplicationExitsOnSuspend,iOS 4 和足够新的设备(即比 iPhone 3G/iPod 2g 更新的设备)上的默认行为是发送-applicationWillEnterBackground:然后暂停您的应用程序(显然使用 SIGSTOP)。如果操作系统后来决定您的应用程序需要退出,它会发送 SIGKILL 而不给您的应用程序更多的 CPU 时间。您需要在
-applicationWillTerminate:
和-applicationWillEnterBackground:
中保存状态;主要区别在于您可以在后者中启动后台任务。(另一个区别是,您可能会在 -applicationWillTerminate 中进行一些“清理”:当您刚刚移动到后台时,这种情况不应该发生,即使在您的应用程序即将退出时释放内存很大程度上浪费了 CPU 时间.)
For the most part, no; sqlite3 writes everything to "disk" (and calls fflush/fsync/etc as appropriate) before returning.
There's one big exception: If there's an uncommitted transaction when you close the database, it'll be rolled back the next time you open it.
Exactly what happens depends on PRAGMA journal_mode: if it's "memory" or "off", the database is likely to be corrupt if your app crashes during a write. I think PRAGMA locking_mode only affects what happens when locks are released, not transactional integrity.
Note that -applicationWillTerminate: is not sufficient anyway! If you haven't set UIApplicationExitsOnSuspend, the default behaviour on iOS 4 and a new-enough device (i.e. newer than iPhone 3G/iPod 2g) is to send -applicationWillEnterBackground: and then suspend your app (apparently with SIGSTOP). If the OS later decides that your app needs to exit, it sends SIGKILL without giving your app any more CPU time. You need to save state in both
-applicationWillTerminate:
and-applicationWillEnterBackground:
; the main difference is that you can start a background task in the latter.(The other difference is that you might do some "cleanup" in -applicationWillTerminate: that shouldn't happen when you're just moved to the background, even though freeing memory when your app is about to exit is largely a waste of CPU time.)