SQLite Forum

New type of transaction (or a new behavior for DEFERRED transactions)
Login
> Whenever an attempt to acquire an exclusive lock to write to a file by transaction A would fail due to the existence of other writer (with an intent to write lock) in transaction B, instead returning SQLITE_BUSY immediately, transaction A would simply release (drop) it's lock allowing transaction B to finish their jobs and new attempts to write (trying to obtain a new lock) would be done automatically by SQLite for transaction A (up to the timeout limit).

The situation as it currently exists has been well documented, known, and researched since the introduction of relation DBMS systems way back in the 1970's and for "concurrent" systems since their inception.

There have been many enhancements made to the SQL language as a result of this observation.  The first, of course, being the introduction of the "FOR UPDATE OF" clause in DB2 back in the late 1970's or early 1980's (I do not remember exactly since I was still in highschool at the time).  This was followed by the introduction of "BEGIN IMMEDIATE" in the mid-1980's or so in order to allow avoidance of the lock-escalation deadlock by utilizing the (by then) well known deadlock avoidance mechanism of *always* acquiring all the locks you need at once, *always* in the same order, and *always* releasing them all when the acquisition of a required lock fails.

 > If this does not make sense to you, then you could at least consider making IMMEDIATE transactions the default. The performance may be lower than DEFERRED transactions, but IMHO it mimics better how a client-server DBMS works, where SQLite handles the retries with it's own mechanism by itself no matter it takes slightly more time, leaving the DEFERRED transaction as an advanced option for those looking for increased performance at the "cost" of having to handle the retries at application level.

SQLite3 is not a client/server DBMS.  Many client-Server DBMS, because they run on a whopping big server that may be thousands of miles away from the client, defer all "conflict detection" until actual COMMIT time.  They can afford to do this because they are (a) very big (b) very fast (c) very far away; and, returning an error "Sorry about your luck" when a commit fails for no apparent reason is acceptable.

The problem with doing what you suggest is that it will lead to undetectable errors.  Because SQLite3 does not have a "server process" that can keep track of all the clients independent doings, there is no way for the SQLite3 library to know what each database file user is doing.  A Client/Server DBMS has a single server process that knows *exactly* what each client is doing and can be *optimistic* in its behaviour because it can detect problems and conflicts later and if they arise then issue a "sorry about your luck" error and abort the transaction -- something which SQLite3, being an in-process data access library, cannot do.

As for making BEGIN IMMEDIATE the default, this is not a good idea.  Besides having a profound impact on concurrency, an application may not always want start a transaction because it intends to perform an update.  An application may begin a transaction in order for a sequence of reads to be repeatable.  Although other mechanisms can exist to ensure repeatable-read, they all require participation of a "server" process to co-ordinate multiple clients -- which does not exist in SQLite3.

You will note that many "wrap around libraries" ("frameworks" as they are called these days -- gigabytes of code that does inscrutable things) may permit one to set that as default.