On Friday, 9 January, 2015 16:43, James K. Lowden <jklow...@schemamania.org> 
said:
>On Wed, 07 Jan 2015 21:47:24 -0700 "Keith Medcalf" <kmedc...@dessus.com> wrote:

>Along the same lines, since you mentioned it,

>>  in an SQLite database you can do:

>> BEGIN
>> SELECT ...
>> SELECT ...
>> SELECT ...
>> SELECT ...
>> COMMIT

>> and the view of the database seen by this connection will be
>> consistent even though "some other process" modified the tables used
>> in query 3 while query 2 was executing.  Even if those changes are
>> commited by the writer process, the above process will not see them
>> until the COMMIT releases the locks.  I expect other databases do
>> this as well.

>In other DBMSs that I know of -- and afaik standard SQL -- BEGIN
>TRANSACTION has no effect on SELECT. Each SELECT is atomic, of course,
>but there's no way to hook two SELECTs together to make them see one
>database state. That's what JOIN is for.  :-)

Yes, it is a part of the SQL Standard isolation levels in excess of the default 
default of READ COMMITTED.  Different vendors call the isolation levels by 
different names -- MS SQL Server calls them Read Uncomitted, Read Committed, 
Repeatable Read, Snapshot, and Serializable; DB/2 calls them No Commit (similar 
to autocommit), Uncommitted Read, Cursor Stability, Read Stability, Repeatable 
Read.  DB/2 Repeatable Read = MS Serializable (which is the SQL Standard 
Serializable isolation level).  Cursor Stability = Read Committed.

These describe the isolation to be maintained be simultaneous Units of Work.  
The standard Read Committed/Cursor Stability level does not isolate the unit of 
work from changes made (and committed) by other units of work.  The higher 
levels do.  For example, if a unit of work is executed with Read Committed the 
two select statements may see changes to the database which were committed on 
another unit of work.  With Serializable / Repeatable Read, those changes will 
not be visible.  In fact, the database will not permit the updates to rows that 
have been read at the Serializable / Repeatable Read level.

http://publib.boulder.ibm.com/iseries/v5r1/ic2924/info/db2/rbafzmstisol.htm
http://msdn.microsoft.com/en-us/library/ms173763.aspx

>A common error among inexperienced programmers is to assume that BEGIN
>TRANSACTION works as you describe above: that it isolates SELECT from
>competing updates.  But a transaction is not a lock!  A better mental
>model is the one defined in the standard: BEGIN TRANSACTION defines a
>unit of work that either will or will not be applied to the database in
>its entirety (depending on COMMIT or ROLLBACK, of course).  It has a
>role to play in maintaining database integrity.  It really has nothing
>to do with isolation.

Indeed it does.  It is up to the programmer to set the isolation levels 
required and then set the transaction (unit of work) boundaries correctly.  
Most only know or use the default Read Committed / Cursor Stability level which 
is usually the default mode, which works as you describe.

SQLite in standard journal mode uses "read committed/cursor stability" 
isolation between connections to the same database.  I have double checked, and 
if you surround multiple selects with explicit begin/end, then that unit of 
work cannot be interrupted by updates and hence you then have "Repeatable Read" 
isolation.  Whether or not this is intended it must work this way because the 
introduction of a unit of work means that there is intent to update at some 
point and the database, within the unit of work, must maintain cursor stability 
(at least) until an actual update occurs which will escalate the shared lock to 
an exclusive lock.  In fact, if you do this, you will be unable to commit the 
update transaction until the other unit of work is completed (even if it only 
contains select statements).

In WAL mode the transaction mode is always snapshot between units of work on 
separate connections, but only one connections' unit of work can convert to 
"update" at a time.  Other connections doing just selects between a BEGIN 
COMMIT will continue to see the same snapshot even if another connection 
commits database changes.  It appears that the concurrent snapshot can also 
escalate to an update lock is released by another and sometimes it cannot -- if 
it is the head of the uncommitted WAL, it can, if it is not, it cannot.

>Interesting discussion, Keith.  Thanks for the clarification.

---
Theory is when you know everything but nothing works.  Practice is when 
everything works but no one knows why.  Sometimes theory and practice are 
combined:  nothing works and no one knows why.




_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to