Thank you very much Keith. Apologies for my imprecise vocabulary, and the use of the same "snapshot" word with different meanings.
I have used the term "snapshot isolation" as used in https://www.sqlite.org/isolation.html; But I'll remember about REPEATABLE-READ isolation. I also thank you very much for confirming that preventing checkpoints allows the WAL markers to remain valid. My goal is to provide a set of concurrency primitives that are useful for GUI app developers. I'm learning a lot about SQLite in the process, of course. On Sun, Sep 29, 2019 at 2:13 PM Keith Medcalf <kmedc...@dessus.com> wrote: > > On Sunday, 29 September, 2019 01:28, Gwendal Roué <gwendal.r...@gmail.com> > wrote: > > >But now I fail to understand the indented use case of sqlite3 snapshots.. > >Why allow to reuse snapshots with several calls to open()? Why do they > >exist at all, since we can already profit from snapshot isolation with > >one transaction (at the cost of keeping it open)? > > The sqlite3_snapshot_* interfaces allow you to record information about > transactions maintained by the WAL transaction manager. The interface DOES > NOT manage the WAL transaction manager nor does it manage your so-called > snapshots (which are not snapshots). It allows you to "get" information > about a particular point-in-time location in the WAL transaction log and > "goto" a specific point-in-time in the WAL transaction log, to "free" the > memory used to record this information, and to "cmp" which of two > structures point to a later point-in-time in the WAL transaction log. > > They do NOT modify or control the WAL transaction system or the WAL file. > You are responsible for doing this. > > https://sqlite.org/wal.html > > So, *IF* you want to maintain the availability of a specific point in time > in the WAL transaction history, they YOU must make sure that YOU do not > erase that particular point-in-time location by checkpointing the WAL > transaction log. You have the capability of doing this by disabling the > autocheckpoint mechanism and controlling when you do checkpoints. The WAL > transaction system neither knows nor cares that you happen to have recorded > some information about a particular point-in-time offset in the WAL file. > > It is sort of like "No Smoking" signs. The sign does not mean that you > cannot smoke. It means that someone posted a sign that says "No Smoking". > The fact that there is a sign and what it says is an entirely separate fact > that has no bearing at all on whether or not one may smoke, nor does the > sign somehow magically prevent smoking, nor will it prevent you from > catching on fire and smoking as a result thereof. It is merely a sign that > has something written on it which someone stuck up on the wall (or whatever > support structure it is stuck to). And what is written on the sign is > entirely independent of any other state of affairs. > > >For information, my quest for snapshot protection has met some success ( > >https://github.com/groue/GRDB.swift/pull/625) > > This appears to be updating a wrapper interface to SQLite3 so that if you > happen to have a point-in-time location recorded, then the automatic WAL > checkpoint system is disabled, plus doing some prevention to protect users > of the wrapper from modifying (checkpointing) the WAL transaction log if > they happen to have some recorded "points-in-time" that are dependent on > not modifying the WAL transaction log. (ie, things that you should be > doing yourself so as to not shoot yourself in the foot). > > >Given I control the connections to a given database file, I am able to > >open one writer connection, and, on demand, up to N read-only connections. > > >Those N reader connections allow concurrent database reads. Those "reads" > are > >generally wrapped in a deferred transaction which provides snapshot > >isolation. > > No, it provides REPEATABLE-READ isolation. There is no actual "snapshot" > taken and no snapshot exists. You are merely not seeing data written to > the WAL transaction log at a point-in-time subsequent to the point in time > at which you commenced the "repeatable-read". > > The sqlite3_snapshot_* interface merely provides a way to record > information about this repeatable-read point-in-time position in the WAL > file so that you can go back to that "repeatable-read" point-in-time > location sometime in the future IF IT STILL EXISTS in the WAL transaction > log. Since YOU are in control of whether or not the WAL file is > checkpointed, then YOU are in control of whether this point-in-time still > exists in the WAL transaction log. If you remove data from the WAL > transaction log by performing a checkpoint (which moves transactions into > the main database file) then this recorded "point-in-time" may no longer > exist in the WAL transaction log. > > >At the end of this transaction, the reader connection becomes > >available for another read. > > Yes. And by default when the transaction starts it gets a repeatable-read > isolation "point-in-time" stamp corresponding to the last transaction > written to the WAL transaction log which has been committed, or gets the > current point-in-time representing the "current database" if there are no > committed transactions in the WAL transaction log. > > >One can now create a "snapshot". Those snapshots use the same pool of N > >readers: snapshot reads are then wrapped in a deferred transaction and > >sqlite3_snapshot_open. At the end of this transaction, the reader > >connection becomes available for another regular read or for another > >snapshot read. > > There is the error. There is no "snapshot". You do not "create a > snapshot". You record a point-in-time marker location within the WAL > transaction log. Think of it as taking a picture of the state of the > moving van after it has been half filled. You can go back to the > point-in-time represented by this picture right up until the moving van > drives to the new location and unloads those boxes at your new house (does > a checkpoint). When this happens, you still have the picture, but now a > new van has arrived to be loaded up and the old one is gone forever. While > you still might have the picture, it is just a bunch of data that is not > useful for anything except entertainment. > > >In order to protect unused snapshots, checkpoints are prevented as long > >as there exists snapshots, with sqlite3_wal_hook(). > > There are no "snapshots". There are merely recorded point-in-time markers > from the WAL transaction log. If you modify the WAL transaction log by > performing a checkpoint operation, your "point-in-time" may no longer be > accessible because that "point-in-time marker" may no longer exist in the > WAL transaction log. > > >I **really** hope this protects snapshots for good. Of course, a > >confirmation from knowledgeable people would be appreciated :-) > > Yes. If you do not remove transactions from the WAL transaction log then > all the point-in-time markers before each of these transactions will still > exist. As soon as you move a committed transaction from the WAL file to > the main database (this is called a checkpoint), the "point-in-time" marker > prior to that transaction no longer exists in the WAL file, so you "cannot > get there from here" (you cannot go to that point-in-time location because > it is no longer recorded in the transaction log). > > -- > The fact that there's a Highway to Hell but only a Stairway to Heaven says > a lot about anticipated traffic volume. > > > > _______________________________________________ > sqlite-users mailing list > sqlite-users@mailinglists.sqlite.org > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users > _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users