Reputation: 1
I have an android application that runs on a slightly customized version of Android 10. The application persists data to Room db.
Recently, backend server has logged 40 cases of partial data loss where both newly inserted rows and updates done to existing rows have been deleted from the database.
My assumption is that since SQLite initially writes data to a WAL file, corruption of this file is resulting in loss of data that is not yet persisted to the original db.
I have tested this out by intentionally corrupting the WAL file by writing garbage data to it and sure enough, all the data that hasn't been checkpointed is lost.
Now, how do I identify what is corrupting the WAL file?
Links I've referenced while debugging this: How To Corrupt An SQLite Database File Debugging file corruption on iOS
Upvotes: 0
Views: 112
Reputation: 57053
Now, how do I identify what is corrupting the WAL file?
As per the linked causes of corruption. It is likely due to misuse of the database file(s) rather than an issue with SQLite itself.
Perhaps the most frequent is a backup/restore or copy process that does not consider the WAL file as being part of the database. i.e. just backing up and thus restoring just the database file itself, thus either leaving a then invalid WAL file or an empty WAL file which can result in the data store in the WAL file being lost.
Perhaps try using the setJournalMode
to set the mode to TRUNCATE. This should resolve the issue due to the different logging methodology.
I have tested this out by intentionally corrupting the WAL file by writing garbage data to it and sure enough, all the data that hasn't been checkpointed is lost. Recently, backend server has logged 40 cases of partial data loss where both newly inserted rows and updates done to existing rows have been deleted from the database.
As explained above, yes corruption of the WAL can lead to missing data; BUT it is not the only way that data can be apparently lost. For example IGNORE
d conflicts (e.g./most likely UNIQUE conflicts) could result in the apparent disparity.
Are you excluding the possibility that rows may exist in the embedded database but not in the backend?
I don't have a logging system in place
Perhaps you should consider doing so (on a temporary basis). Perhaps via a TRIGGER or TRIGGERS. Although Room doesn't cater for TRIGGERs via annotation they can still be added using either or both the onCreate
and onOpen
callbacks, furthermore you can also have tables, such as a table for logging, that Room is unaware off (when Room checks the intended v actual schema it bases this on the @Entity
annotations to build the intended an only checks that the actual schema includes).
perhaps consider using a similar TRIGGER for the BEFORE action as well as a TRIGGER for the AFTER action.
With such a logging system in place losses that are not due to WAL file corruption may come to light.
You may wish to refer to https://www.sqlite.org/wal.html (and perhaps consider what you could do in regards to checkpointing)
Upvotes: 0