On 20 Nov 2017, at 7:37pm, Jim Dossey <[email protected]> wrote:

> sqlite3_prepare("SELECT * FROM table;");
> while (sqlite3_step() == SQLITE_ROW) {
>     x = current_rowid();
>     sqlite3_exec("UPDATE table SET value=1 WHERE rowid=x;");
>     sleep(1);
> }

In SQLite, as in other SQL engines, all access to a database must be done 
inside a  transaction.  If SQLite was being stuffy and uncooperative if you 
tried

        SELECT * FROM table

without declaring a transaction, you would get an error back telling you you 
did it wrong.  What you would be expected to do would be

        BEGIN;
        SELECT * FROM table;
        COMMIT;

Operations on the database by commands like SELECT and INSERT are minimal.  
It’s the COMMIT which does all the hard stuff.  Locks start off as a READ lock, 
and are promoted to a WRITE lock the first time they try to do any writing.

However, SQLite is polite and convenient and if it sees you’ve forgotten to 
open a transaction, it opens one for you, and closes it as soon as possible, to 
let other connections get a lock as soon as possible.  Within your code above 
this would be

sqlite3_exec("BEGIN");
sqlite3_prepare("SELECT * FROM table;");
while (sqlite3_step() == SQLITE_ROW) {
    x = current_rowid();
    sqlite3_exec("UPDATE table SET value=1 WHERE rowid=x;");
    sleep(1);
}
sqlite3_exec("COMMIT");

The COMMIT cannot go earlier because until you have received your SQLITE_DONE 
from the loop you are still executing your SELECT statement.

Reviewing your proposed procedure knowing the above you can see that you are 
still maintaining a write lock on the database even between UPDATEs, because 
the transaction which contains them all is still running.

Simon.
_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to