Re: [pysqlite] database locked

"Eric S. Johansson" <[email protected]> Tue, 27 May 2008 10:22:45 -0400
Newsgroups gmane.comp.python.db.pysqlite.user
Message-ID <[email protected]>
thank you to everyone who responded to my query.  I'll try to increase my 
understanding through questions over the next couple days.

Dennis Lee Bieber wrote:
> 	I presume multiple connections are active... 

yes, in this environment, there are anywhere from one to 20 processes accessing 
the database at any one time.  Currently, I only use the database for one thing 
(tracking metadata) but I'm probably going to expand it to do message source 
reputation classification.  This will probably double the number of processes 
accessing the database.

(Question: what's the better solution for setting up databases when you have two 
tables, 150,000 entries or more and the other with potentially millions.  Should 
each table have its own set of files or should I put both tables in one file?)

> As I recall, SQLite can
> not commit changes until all other in-work transactions have exited --
> and "in-work" means some other connection has performed even just a read
> operation, even if no data modification has been done. In essence, for
> one transaction to COMMIT, all others must close first (commiting a
> read-only transaction is probably permitted, but if multiples are trying
> to update/insert, most will have to rollback and retry).

interesting.  I thought I could do one commit while reads were outstanding but 
your description would explain behavior I've seen (as load increases, so does 
the time to completion.)

(Question: is there any relationship between the number of records returned in 
time the database is locked?  There is one point in my application where I query 
for a "screens" worth of data and get far more than I need because I need to 
sort it and massage it for presentation.  Would there be value in leading SQL 
light sort and then return only the first X elements?)

> 	A long timeout value probably is going to result in even MORE
> problems, as the transaction attempting to commit is going to block more
> and more other transactions from even starting. The transaction trying
> to commit is waiting for all others to exit, and new transactions can
> not be started while one is in a write(wait) mode.

then the timeout doesn't do what I thought it did.  :-) before your explanation, 
I thought it meant that the attempts to update would be queued behind the lock 
and then as the system lock released, it would allow the transactions to complete.

> 	As others have mentioned, your solution is, in your own words,
> "retrying until" you succeed... The key is that "retry" for SQLite means
> "rollback and repeat the entire transaction". Hopefully your
> transactions don't consist of "get parameters from user; select
> record(s); display to user; wait for user to edit screen; collect edits;
> update record(s); commit" (if it is... you'll probably want to do a
> commit after the select, and then when you get to the "collect edits"
> part, append a copy of the original select and validate that those
> records have not changed while waiting for the user; no change, do the
> update... changes? commit/rollback, advise user, and redisplay using the
> newer versions)

No, it's far simpler than that.  All the updates can be reconstructed and 
retried forever and a day if need be.  Also, I'm perfectly happy with last write 
wins semantics.

(Question: how do I differentiate a "must retry" event from "something else 
died" events?  is this a Python exception or something where I need to look at 
the error result)