18
votes

At the WWDC 2013 session '207: What's New in Core Data', they mention that you can enable SQLite WAL by passing an options dictionary when adding a persistent store:

@{ NSSQLitePragmasOption: @"journal_mode = WAL" }

(which is available on iOS4+ and will be the default for future iOS versions).

I'm wondering whether this would generally be a good thing to enable in my app for earlier iOS versions too.

I've consulted the SQLite page about write ahead logging and the disadvantages they mention, most of them seem not to apply to iOS apart from:

  • WAL might be very slightly slower (perhaps 1% or 2% slower) than the traditional rollback-journal approach in applications that do mostly reads and seldom write.

pretty much all the advantages do sound like they'll probably be a benefit on iOS:

  • WAL is significantly faster in most scenarios.
  • WAL provides more concurrency as readers do not block writers and a writer does not block readers. Reading and writing can proceed concurrently.
  • Disk I/O operations tends to be more sequential using WAL.
  • WAL uses many fewer fsync() operations and is thus less vulnerable to problems on systems where the fsync() system call is broken.

I'm asuming (perhaps subject to doing some checks on my app to make sure it doesn't slow things down) that this would be a good thing to enable, but is there any downside I should watch for or any known issues?

2

2 Answers

18
votes

http://pablin.org/2013/05/24/problems-with-core-data-migration-manager-and-journal-mode-wal/ suggests that their could be issues with migrations, in particular:

When you use a Migration Manager, Core Data will create a new database for you, and start copying the entities one by one from the old DB to the new one.

As we are using journal_mode = WAL, there’s an additional file besides DB.sqlite called DB.sqlite-wal.

From what I can tell, the problem seems to be that Core Data creates a temporary DB, inserts everything there, and when it renames it to the original name, the -wal file is kept as a leftover from the old version. The problem is that you end up with an inconsistent DB.

(also mentioned on https://github.com/magicalpanda/MagicalRecord/issues/490 - which suggests that if you use magical record then it is already defaulting to WAL )

2
votes

Regarding the bug that occurs with non-lightweight migrations that involve subclassing NSMigrationManager, which I've re-reported to Apple as Bug 16038419.

I've also made a different, method-swizzling workaround which patches the bug in cases where you always want to use legacy delete/rollback journaling. As I understand it, Pablin's fix is for cases when you want to use WAL except during migrations. Also, you can see that bug occur in this video.