On 2016/11/15 10:34 PM, Jens Alfke wrote:
On Nov 15, 2016, at 10:57 AM, Simon Slavin <slav...@bigfraud.org> wrote:
sqlite> PRAGMA checkpoint_fullfsync;
1
I wasn’t aware of that pragma. Just tried it on my Mac (10.12.1), and its value
is 1 even if I don’t first set pragma fullfsync; i.e. it defaults to 1.
(Contradicting the docs.)
So it appears that on macOS, SQLite does use F_FULLFSYNC when checkpointing,
but not at other times that it fsyncs. What does that mean in actual use,
assuming that I always use WAL mode? Is there still an opportunity for
corruption in the face of power failures?
(Sorry to be frothing at the mouth about this; but my team’s dealing with a few
users/customers whose apps encounter db corruption, on Android as well as
macOS, and we’re getting really frustrated trying to figure out what’s going
on.)
Quite OK to be unsettled by learning that a flaw in the system that you
assumed did not exist, might be the cause of your troubles. I think
however something is missing in the complete understanding, so to be clear:
Calling F_FULLFSYNC when checkpointing or otherwise invokes a contract
between the running software (your system) and the Operating System
whereby the Operating system promises to A - put the current buffer's
worth of written data INTO the BUS feeding the writable media, AND B -
then asking said media to confirm the writing has happened (committed)
BEFORE handing back control (moving your thread pointer along). This is
not exactly the same for all OSes, but more or less similar.
This can slow down things, but sometimes the security is worth the price
paid in latency. However, Hard drive manufacturers tend to sometimes lie
about having committed your data. It is a well known and almost
universally used method in standard desktop / laptop computers for the
harddrive to tell the OS that: "YES indeed, I have committed" when in
fact it is still piping data into the platters. Yes SSD's are better at
this by simple virtue of lower latency from buffer-to-silicone, but they
are not above lying either.
This means that unless you have a SERVER quality drive with typically
its own battery-backup that guarantees ANY buffered writes to reach the
platters, there simply is zero guarantee that all writes WILL go to
disk, and any normal system that guarantees it lies.
This does not mean however that you should be experiencing corruption.
SQLite might not be able to guarantee all writes reaching the disk, but
in most cases, if a final write did not happen, the usual last step in
committing a transaction is deleting / truncating a journal file or
writing a checkpoint marker or such, which, if it did not happen, should
have the entire write roll back (next time you open the DB) and leave
you in a non-corrupt state. IF this does not happen it means a write may
have happened out of order (not very common but can happen) or some
other worse problem occurred - most importantly, FULL_FSYNC isn't the
wild goose to be chasing. Whether or not any write happened is never an
acceptable cause of corruption, so trying to wrestle with the thing that
promises to make writes happen "more" as a causal relation to a
corruption problem, is simply moot. (This is vigorously tested with
every release of SQLite too).
If you can get the DB files (journals and all) from such a system where
a user claims to be able to reproduce the corruption reliably, that
would be an easy thing to check and the Devs here might learn something
from it. You can simply make something that copy all the DB files before
opening them at startup, until you have produced a corrupt DB, then
those last copied files will be the corrupted DB files that can be
investigated.
Good luck!
Ryan
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users