We found that using SQLITE memory mapped I/O (mmap_size > 0) in OSX isn't usable in any way shape or form. It will inevitably lead to catalog corruption if you hard-reboot OSX, even without the database or application open.
We've tried FULLSYNC and F_FULLFSYNC, but it makes no difference. Repro steps: a) Run our application and write stuff to the database b) Close our app & wait for the .wal file to disappear AND the app to disappear from activity monitor c) Wait another 2 minutes d) Copy your SQLITE db file to a network share e) Hard reboot OSX f) After the reboot, copy the same SQLITE db to a second network share g) File compare (d) vs. (f) Observe: The files in (c) and (e) are virtually never identical. NOTE: There is no application or SQLITE is involved here. The app is closed. It (should have) checkpointed and flushed properly (FULLSYNC + FULLFSYNC). However, the MAC doesn't seem to write the database to disk. So once you hard-reboot you don't have the same file anymore. SQLITE detects this as catalog corruption around 25% of the time, but a file compare shows differences pretty much 100% of the time. Not just benign differences in unused pages - the header is more often than not different as well. Without the Hard reboot our database always survives a close. You can gracefully shutdown the application, pkill it, force terminate, crash it, soft reboot - it all survives. However, once you hard reboot OSX - even AFTER the app is closed - it has a very high probability of corrupting our database. I've seen a worse case scenario where the hard reboot followed an app graceful shutdown by 12 hours, and it still corrupted the database. This is so easy to reproduce I'm not sure why this isn't reported as a large-scale problem? It also only reproduces on OSX (both El Capitan and Mavericks) - Android, iOS, PC all work fine. Anyway, it's not a big deal for us to set mmap_size to 0 to work around this. The big problem I have however is the .wal. We use SQLITE from multiple threads, and as such it's using shared memory to read/write the .wal. However, if persisting memory mapped files on OSX is so unreliable, then how can the .wal be expected to survive a hard reboot... So I'd also like to have a way to not use memory mapped I/O for .wal files, but I don't think there is a way unless I change the architecture of my app to have single-threaded access to SQLITE? Or is there another way? - Deon