On Tuesday, 9 July, 2019 20:34, Andy Bennett <andy...@ashurst.eu.org> wrote:

>However, the wording for WAL mode is confusing me.

>isolation.html says 'all transactions in SQLite show "serializable"
>isolation.' but it also says 'In WAL mode, SQLite exhibits "snapshot
>isolation"'.

>Snapshot Isolation and Serializable often (in other engines) mean
>different things at commit time (
>https://blogs.msdn.microsoft.com/craigfr/2007/05/16/serializable-vs-
>snapshot-isolation-level/
>), but SQLite seems to say that the snapshot isolation is upgraded to
>serializable by forbidding readers to upgrade to writers if another
>writer got in before them:

>'The attempt by X to escalate its transaction from a read transaction
>to a write transaction fails with an SQLITE_BUSY_SNAPSHOT error because
>the snapshot of the database being viewed by X is no longer the latest
>version of the database.'

>So far, so good.

>However. the definition of SQLITE_BUSY_SNAPSHOT at
>https://sqlite.org/rescode.html#busy_snapshot says:

>-----
>1. Process A starts a read transaction on the database and does one
>   or more SELECT statement. Process A keeps the transaction open.

>2. Process B updates the database, changing values previous read by
>   process A.

>3. Process A now tries to write to the database. But process A's view
>   of the database content is now obsolete because process B has modified
>   the database file after process A read from it. Hence process A gets
>   an SQLITE_BUSY_SNAPSHOT error.
>-----

>In particular 'Process B updates the database, changing values
>previous read by process A.' seems to suggest that values read 
>by A have to be changed to effect the SQLITE_BUSY_SNAPSHOT 
>error in A.

SQLite does not track individual "rows" or "tables" being changed.  In (2) 
"changing values previously read by process A" means the database has changed 
since process A's view of the database was created.  What exactly changed is 
immaterial, since tracking of changes only occurs at the "whole database" level.

>Is that last quote just imprecise writing or is there really a
>difference between SQLite's Snapshot Isolation in WAL mode and 
>its Serializable isolation in ROLLBACK mode?

Yes, there is a difference.  In rollback mode, a transaction merely places a 
shared lock on the database preventing any changes whatsoever from being 
committed to the database.  All outstanding transactions must be "closed" 
before a commit may proceed (acquire an EXCLUSIVE lock on the entire database 
including all its rows in all tables).  Thus "changes" to the database are 
"serialized" because they can only occur in series and only when nothing else 
is "looking" (since looking requires at least a read lock, which will prohibit 
the update from being committed).

WAL mode however, is different.  When you commence a "read transaction" in WAL 
mode you are creating a *snapshot* of the database at that time (actually, the 
reference to *snapshot* is incorrect, the actual isolation level is "repeatable 
read").  "repeatable read" markers can be thought of as "timestamps"  -- that 
is, a process holding a "repeatable read" lock against the database can see the 
database up to the time of its "timestamp" was created (when the lock was 
obtained).  It cannot see changes that are made *after* that time.  If another 
process obtains a "repeatable read" timestamp that is the same as one already 
obtained by another process, and then commits those changes, the original 
process is still holding a "repeatable read" lock on the database as it existed 
BEFORE the change was committed.  Thus it cannot update the database because it 
is seeing a "historical" version of the database and not the "current" view of 
the database -- that is it is looking at the database as it was at the time it 
obtained its "repeatable read" timestamp, and cannot be permitted to make 
changes since it is looking at an "old view" that does not represent an 
updateable state of affairs.

In effect WAL is a "stack of changes" to be applied to the database file.  When 
a read lock is obtained, the position in the stack is remembered.  If something 
else adds more data to the stack, then the original locker is no longer "top of 
stack" and cannot write changes to the database because it cannot "see" the 
changes made after it entered repeatable read isolation.

see https://www.sqlite.org/wal.html
especially 2.2 Concurrency

-- 
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

Reply via email to