Thanks a lot for the explanation Igor. -- Marco Bambini
On May 14, 2009, at 1:55 PM, Igor Tandetnik wrote: > "Marco Bambini" <ma...@sqlabs.net> wrote > in message news:aa7dd05f-4679-43dd-9dd3-2ba6b98af...@sqlabs.net >> I have two threads that are writing 2000 rows each to the same >> database at the same time. >> I am using sqlite 3.6.13 compiled with SQLITE_THREADSAFE=1. >> >> Each client executes this code (pseudo C code): >> void write (sqlite3 *db) { >> int i; >> >> for (i=1; i<=2000; i++) { >> if (sqlite3_get_autocommit(db) != 0) sqlite3_exec(db, "BEGIN >> IMMEDIATE;", ...); >> sqlite3_exec(db, "INSERT INTO....", ...); >> if (sqlite3_get_autocommit(db) == 0) sqlite3_exec(db, >> "COMMIT;", ...); >> } >> } >> and db is shared between the two clients. > > You have a race condition here: between the calls to > sqlite3_get_autocommit and sqlite3_exec, the other thread could very > well have issued a BEGIN or a COMMIT of its own. Between the time you > check the condition and the time you act on it, the condition could > have > changed. > > Besides, the documentation on sqlite3_get_autocommit has this > sentence: > If another thread changes the autocommit status of the database > connection while this routine is running, then the return value is > undefined. In other words, sqlite3_get_autocommit is explicitly not > thread-safe. > > Since you only run one INSERT per transaction anyway, why do you feel > you need explicit BEGIN and COMMIT? > >> At the end of the loop, instead of having 4000 rows I have 3976 rows >> (it's random, sometimes I have 3972 or 3974). >> sqlite3_exec doesn't returns any error during the INSERT statement, >> but I have some errors during the BEGIN IMMEDIATE, errors are all: >> SQL logic error or missing database (printed with sqlite3_errmsg). > > Your use of sqlite3_errmsg is itself very likely a race. Between the > time you detect an error and the time you retrieve error message, the > other thread could have run some statements that modify the error > message. Moreover, between the time you call sqlite3_errmsg and the > time > you actually print the string pointed to by the char* pointer the > function returns, the string may be modified or even deallocated. > > Igor Tandetnik > > > > _______________________________________________ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users