Re: [pysqlite] database locked

Gerhard Häring <[email protected]> Mon, 02 Jun 2008 09:19:27 +0200
Newsgroups gmane.comp.python.db.pysqlite.user
Message-ID <[email protected]>
Dennis Lee Bieber wrote:
> [...]
> 
> 	Based upon a box in "The Definitive Guide...", pysqlite2 sort of
> wraps modification SQL in transactions, and commits when the SQL
> operation changes type... So the implicit BEGIN happens when the cursor
> executes an INSERT/UPDATE/DELETE/REPLACE, and the transaction continues
> through subsequent similar statements... But issuing a SELECT /after/
> issuing an INSERT (for example) results in pysqlite2 doing a implicit
> COMMIT before the SELECT. 

Wrong! There are only two possibilities where pysqlite commits.

1) You call .commit() on the connection object
2) You execute a DDL statement (CREATE TABLE/CREATE VIEW/...). pysqlite 
then does an implicit COMMIT before these

Transactions are implicitly opened on the first encountered DML 
statement (INSERT/UPDATE/DELETE/REPLACE).

> [...] There is a warning not to use "... ON CONFLICT
> ROLLBACK" because it confuses pysqlite2.

I removed the warning a while ago, because I now call an SQLite API 
function to detect if *SQLite* implicitly did a ROLLBACK.

> [...]
> However, note the other thing in my tests... A SELECT does not
> finish until all the data has been read from it! If you are looping over
> a large number of records, and each record takes, say 0.5 seconds to
> process (slow machine?), that cursor will have a shared read lock during
> the entire looping; whereas doing a .fetchall() and then looping over
> the results frees the cursor practically immediately (but will take a
> bit more memory to store the list of all results rather than one row at
> a time). [...]

Yes, that's correct and I should probably add a note about this to the 
documentation.

FWIW this is a good place to use cursor_factory and provide your own 
cursor class that transparently does the fetchall() after the execute() 
if you encounter this problem.

-- Gerhard