Glossary
SQLite WAL (Write-Ahead Log)
The SQLite write-ahead log (-wal file) holds recent changes not yet merged into the database; on Android it often contains the newest messages.
In write-ahead logging mode, SQLite does not change the main database file directly. It appends modified pages to a sidecar file named <database>-wal, and a shared-memory index <database>-shm tells readers which version of each page is current. A checkpoint later copies the pages back into the main file, by default once the WAL reaches about 1,000 pages or when the last connection closes.
Most Android databases run in WAL mode (Android 9 made a "compatibility WAL" the default for apps that do not choose a journal mode), so on a seized phone the most recent rows, such as the last messages in msgstore.db or mmssms.db, may exist only in the WAL. Older versions of a page can also survive in the WAL after a record was deleted from the main file.
Handling rules:
- Always collect
name.db,name.db-walandname.db-shmtogether, with their timestamps. - Work on copies. Opening a database read-write with
sqlite3or a GUI checkpoints the WAL and deletes it, which destroys the older page versions. - Opening with
?immutable=1ignores the WAL entirely: you will not see the newest data. - Use a parser that replays WAL frames without checkpointing, or compare results with and without the WAL to find recently changed or deleted rows.
Older or explicitly configured databases use a rollback journal (name.db-journal) instead; it can hold the pre-change copy of pages. See the SQLite WAL documentation and the SMS and MMS page for an Android example.