9 ms·
SQLite's documentation about its durability properties is unclear
- topspin 1y ago[flagged]
- meindnoch 1y ago[flagged]
- anotherhue 1y agoI'm laughing but mostly crying. Reliability is a dirty word, because it almost always comes at the cost of 'growth'.
- 3eb7988a1663 1y agoIt is the weekend. Most people use this site to avoid doing work. Edit: whoops, it is Friday! Gave myself a long weekend, and was just default thinking it is Saturday.
- lyjackal 1y agoit's Friday, and I'm avoiding doing work
- 3eb7988a1663 1y agoHa! Whelp, it is my weekend.
- cenamus 1y agoSo this article ask exactly the same as the reply do Dr Hipps comment, just in a 1000 words, instead of 10? Whether the docs are out of sync?
- topspin 1y ago> Whether the docs are out of sync? Were this a one off, you would have a point. It isn't, however. My experience over many years has been that you can't ever be certain about what is actually going on, based on the documentation alone, and that you wind up in Reddit and Stack Overflow and a plethora of blog posts attempting to figure it out. With LLMs, we have only more sources of contradictory and chronically obsolescent input. There is an actual problem here. However I can see that, based on the contributions from the SQLite downmod mafia, this talk isn't welcome, so I'm off to some other thing. Have a nice weekend, I suppose.
- mtmail 1y ago> the SQLite downmod mafia Oh, come on. There's no open or secret attempt at censoring talk about sqlite on HN. (The story is #11 on the frontpage the minute the comment was made.)
- NewsaHackO 1y ago> By default, SQLite is not durable, because the default value of journal_mode is DELETE, and the default value of synchronous is FULL, which doesn't provide durability in DELETE mode. From the documentation, it seems like synchronous being FULL does provide durability of the database in DELETE mode, as FULL means it calls fsync after the transaction is completed. I think you may be confusing durability of the journal file with durability of the database. I don't think WAL can ever really have a durable transaction; it is essentially based on leaving a transaction open until it gets "check-pointed" or actually committed to the database file.
- mlyle 1y ago> I don't think WAL can ever really have a durable transaction; it is essentially based on leaving a transaction open until it gets "check-pointed" or actually committed to the database file. In general: WAL means you write the transaction to the WAL, fsync (in sqlite, this depends upon the sync mode], and then return it's done to the application. The transaction is then durable: even if the database crashes, the contents of the WAL will be applied to the database file. Checkpointing later just lets you throw away that part of the WAL and not have to replay as much to the database file.
- agwa 1y agoMy understanding of DELETE mode is that the transaction is not committed until the rollback journal file is deleted - if the rollback journal is present when sqlite opens a database, it applies the rollback journal to undo the changes that the transaction made. See https://www.sqlite.org/atomiccommit.html#1_deleting_the_rollback_journal https://www.sqlite.org/atomiccommit.html#1_deleting_the_roll... If the directory containing the rollback journal is not fsynced after the journal file is deleted, then the journal file might rematerialize after a power failure, causing sqlite to roll back a committed transaction. And fsyncing the directory doesn't seem to happen unless you set synchronous to EXTRA, per the docs cited in the blog post.
- NewsaHackO 1y ago>if the rollback journal is present when sqlite opens a database, it applies the rollback journal to undo the changes that the transaction made. See https://www.sqlite.org/atomiccommit.html#1_deleting_the_roll https://www.sqlite.org/atomiccommit.html#1_deleting_the_roll... I don't follow. How would fsyncing the rollback journal affect the durability of the actual database? Do you actually think that the database would reapply an already committed journal whose ID in the header already indicates that the transaction was committed, when the database is already consistent? I really think you should re-review the definition of durability of a database, especially before saying the creator of SQLite is incorrect about its implementation.
- bawolff 1y agoI can't help but feel that the difference to other DBs is that they just don't have these knobs or tell you at all.
- agwa 1y agoPostgreSQL has the knobs and I find the documentation about them very clear: https://www.postgresql.org/docs/current/wal-async-commit.html https://www.postgresql.org/docs/current/wal-async-commit.htm...
- d1l 1y agoThis is disingenuous and probably was written this way for HN cred and clicks. Sqlite's test suite simulates just about every kind of failure you can imagine - this document is worth reading if you have any doubts: https://www.sqlite.org/atomiccommit.html https://www.sqlite.org/atomiccommit.html
- agwa 1y agoThat document addresses atomicity, not durability, and is thus non-responsive to my concerns.
- deleted 1y ago[deleted]
- eatonphil 1y ago> Sqlite's test suite simulates just about every kind of failure you can imagine The page you link even mentions scenarios they know about that do happen and that they still assume won't happen. So even sqlite doesn't make anywhere near as strong a claim as you make. > SQLite assumes that the operating system will buffer writes and that a write request will return before data has actually been stored in the mass storage device. SQLite further assumes that write operations will be reordered by the operating system. For this reason, SQLite does a "flush" or "fsync" operation at key points. SQLite assumes that the flush or fsync will not return until all pending write operations for the file that is being flushed have completed. We are told that the flush and fsync primitives are broken on some versions of Windows and Linux. This is unfortunate. It opens SQLite up to the possibility of database corruption following a power loss in the middle of a commit. However, there is nothing that SQLite can do to test for or remedy the situation. SQLite assumes that the operating system that it is running on works as advertised. If that is not quite the case, well then hopefully you will not lose power too often.
- liuliu 1y ago> So even sqlite doesn't make anywhere near as strong a claim as you make. And? If you write to a disk and later this disk is missing, you don't have durability. SQLite cannot automatically help you to commit your writes to a satellite for durability against species ending event on Earth, and hence its "durability" has limits exactly as spelled out by them.
- tiffanyh 1y agoSQLite is an incredible piece of software, and its commitment to backward compatibility is deeply admirable. But that same promise has also become a limitation. v3.0 was first released in 2004—over 20 years ago—and the industry has changed dramatically since then. I can’t help but wish for a “v4.0” release: one that deliberately breaks backward compatibility and outdated defaults, in order to offer a cleaner, more modern foundation. Note: I'm not asking for new functionality per se. But just a version of SQLite that defaulted to how it should be used, deployed in 2025.
- umpalumpaaa 1y agoThere was an attempt/experiment to develop SQLite 4: https://sqlite.org/src4/doc/trunk/www/index.wiki https://sqlite.org/src4/doc/trunk/www/index.wiki
- sgbeal 1y agoThe focus of that experiment was to find out of LSM-based storage[^1] would prove to be faster. It turned out that LSM, for SQLite's workloads, did not provide enough benefit to justify the upheaval. [^1]: https://en.wikipedia.org/wiki/Log-structured_merge-tree https://en.wikipedia.org/wiki/Log-structured_merge-tree
- nikisweeting 1y agohttps://turso.tech https://turso.tech I think attracts a lot of the people trying add new features / improve SQLite rough edges
- diekhans 1y agoIt seems like a bug report on what is not clear in the documentation would be highly useful.
- layer8 1y agoDurability also requires the file system implementation and the disk to do the right thing on fsync, which, if I recall past discussions correctly, isn’t a given.
- ericbarrett 1y agoThere are some older fsync() bugs (as famously explored by Postgres developers: https://wiki.postgresql.org/wiki/Fsync_Errors https://wiki.postgresql.org/wiki/Fsync_Errors ) but I'm not aware of any modern mainstream kernel where this is broken. If I'm wrong, please tell me! An application that really wants confidence in a write—to the extent that the underlying device and drivers allow—should use O_DIRECT. Or maybe there is a modern equivalent with io-uring. But that is not easy engineering :)
- jitl 1y agomacOS is a popular OS that has a fast and loose relationship to that syscall without F_FULLFSYNC
- codys 1y agoNothing prevents using O_DIRECT as an open-flag for a fd used in other io_uring operations. But I'm not sure I'd necessarily think of O_DIRECT as a way of improving "confidence in a write". It's a way to get a specific behavior.
- geertj 1y agoTechnically I think you need O_SYNC. O_DIRECT does pretty much the same but its intention is different.
- vlovich123 1y agoO_DIRECT in now way absolves you from needing to call fsync because fsync ALSO sends a signal to the storage device to flush the buffer if it has anything which is important for durability. What OP is referring to is that some drives ignore that signal for performance reasons and there’s nothing SW can do to solve that part. io_uring in no way changes the rules here.
- dang 1y agoRecent and related: SQLite (with WAL) doesn't do `fsync` on each commit under default settings - https://news.ycombinator.com/item?id=45005071 https://news.ycombinator.com/item?id=45005071 - Aug 2025 (90 comments) with a relevant comment by the creator of SQLite here: https://news.ycombinator.com/item?id=45014296 https://news.ycombinator.com/item?id=45014296 (via https://news.ycombinator.com/item?id=45068594 https://news.ycombinator.com/item?id=45068594 - thanks int_19h!)
- sethev 1y agoThe documentation seems pretty clear to me - it describes specifically what each option controls and the implications of using it. Besides debating whether the default behavior is should be described as durable or not, this post's author seems to understand exactly what each option actually does. Perhaps what's unclear is when to select which option?
- agwa 1y agoI found the documentation much harder to parse than the equivalent PostgreSQL docs (https://www.postgresql.org/docs/current/wal-async-commit.html https://www.postgresql.org/docs/current/wal-async-commit.htm...). Also, even if I've understood the docs correctly, a number of people in this thread and elsewhere have come to a different interpretation. I think that's much less likely to happen with the PostgreSQL docs. And I'm sure you can understand why I began to doubt my own interpretation of the docs when SQLite's creator posted a comment saying the exact opposite of what I thought the docs said!
- sethev 1y agoFair! Fwiw, I enjoyed the post - hopefully my comment wasn't harsh. I think it does come down to the definition of durable. The default in SQLite is that the data for a transaction will be written all the way to disk (with an fsync) and the rollback journal will be deleted (but without an fsync). In this model, there is chance of losing only the last transaction and only if the whole system crashes (like a power failure) after deleting the journal but before your file system makes that durable. If your application crashes, you're still fine. That's significantly more durable than an asynchronous commit in Postgres, though. In an asynchronous commit, the transaction will complete before any data is written to disk at all - the data is only in memory, and many transactions can queue up in memory during the wal_writer_delay. All of those will definitely be lost if Postgres stops uncleanly for any reason (for example a crash, oomkill, or power failure).
- avinassh 1y agoI wrote the first article, and I thought documentation is clear, but then I saw comment by Hipp which got confused me: > If you switch to WAL mode, the default behavior is that transactions are durable across application crashes (or SIGKILL or similar) but are not necessarily durable across OS crashes or power failures. Transactions are atomic across OS crashes and power failures. But if you commit a transaction in WAL mode and take a power loss shortly thereafter, the transaction might be rolled back after power is restored. https://news.ycombinator.com/item?id=45014296 https://news.ycombinator.com/item?id=45014296 the documentation is in contradiction with this.
- liuliu 1y agoMarc Brooker said this: https://x.com/MarcJBrooker/status/1960809302333251876 https://x.com/MarcJBrooker/status/1960809302333251876 which echos my sentiment. I will just repost it here: > More broadly, I don't think a single definition of 'durable' (as in ACID D) for transactions is particularly useful. > Much more useful is to ask "what kinds of failures could cause committed transactions to be lost?" All these articles talking about durability as a singular term should be warned. Writing to disk is not durable under certain circumstances. fsync is not durable under certain circumstances. Two-phase commit is not durable under certain circumstances. Multi-data center commit is not durable against the Death Star too.
- deleted 1y ago[deleted]
- yndoendo 1y agoI used SQLite in an embedded life safety system for years. It was storing settings and history events on an industrial MicroSD card. Failure happens for the most common reasons it happens across all other products. 1) MicroSD card started producing bad sectors. 2) Power failure during write. 3) Fraudulent MicroSD being used. Settings section of the database where written so few times that they could be recovered. It was the journaling of events for analysis that where the ones to be lost. Most of the time it was a page or two that was corrupted and the database worked just fine until detailed reporters where created. Settings where also mirrored to a backup location. Unless the client wanted to pay more for history backup it was only retained locally.
- raggi 1y agofsync is rarely truly durable in the sense the article describes. it does help with loss ordering in a lot of cases, and flushes often do some work, but true durability, the idea that after fsync there will not be any rollback or tail loss unless there's catastrophic failure, sorry, nope. everyone in the chain ends up in the hot path being the hotspot, then they break it because y'all are addicted to spamming syncs then they move it to a new api, then slowly the syncs come back on the new api, then everyone moves again layer by layer. somewhat common examples in recent years are nvme vendors who implement nvme flush in terms of just pushing the write cache down, but won't always also finalize and flush in flight or scheduled ftl operations due to the insane worst case latency costs associated. weren't apple also caught doing the same in recent years, in part because their ftl shared memory, bus and privilege with the higher exception levels? there's also the rumors people say about enterprise drives being better here, but not doing so is even a saleable product in those environments: https://www.atpinc.com/technology/ssd-flush-cache-technology https://www.atpinc.com/technology/ssd-flush-cache-technology and some other vendors just have arbitrary firmware patches to compete (that is: you could buy "enterprise grade" hardware second hand and be entirely unaware of the actual command behavior).