Comment by LgWoodenBadger

15 days ago

Maybe it's just me, but the explanations of the cause don't align.

One clue was that during corruption incidents, our metrics showed that SQLite would report copying more pages from the WAL file than were actually available. If there are 10 pages in the WAL file and 20 pages get copied to the database, something is clearly wrong.

vs

it thinks some of the pages have been copied from the WAL into the main database file, but they haven’t. Those pages never get written to the database file, and that data is permanently lost.

The first says "more were copied than existed" but the second says "fewer were copied than should have been."

Like I said, it's probably just me interpreting something incorrectly.

I haven't looked into the actual code fix, but given the "reset" name I have to think it has to do with SQLite "thinking" it has copied more pages than it actually did.

i.e. The checkpoint starts, and a write hits after the modifications to data structures have been done but before the data has actually been put in the database. The process starts over again, but doesn't undo the changes it made to indexes etc. Hence the db thinks it holds pages that don't exist.

That's my interpretation, anyways.

Those seem consistent to me. Some pages weren't written to the WAL (yet?), but something else referenced them or otherwise indicated they existed, so then the other process tried to read them, resulting in the issue in the first quote.

  • The explanation says they were written to the WAL and then not written to the main database file.

My interpretation is that they haven't been copied because they didn't exist?

If you have 10 pages and it tries to copy 20, either those 10 pages wouldn't really be copied, or bogus data would be written.

That's how I read at least. Those things are not mutually exclusive.

Same bug, two angles. Nothing really copies 20 pages, the "20" is just a broken counter. SQLite's internal tally of how many WAL pages it already saved to the main db gets corrupted and reads too high. Since it trusts that tally, it assumes those pages are already saved and skips writing them for real, so when the WAL resets they're gone. The "copied more than existed" number is the bug showing in your metrics; "pages never written" is the actual damage.