On Tue, Nov 16, 2010 at 04:08:16PM +0300, Ruslan Mullakhmetov scratched on the 
>   i got following contradictory replies to my question
> > if i execute query like " insert into tbl( filed ) VALUES ( 1 ); Select
> > last_insert_rowid() as li;" would be it atomic? or  it anyway would suffer
> > from threads?
> from borgan:
> > Hi, i think this will probably be "atomic".
> > What i mean is the transaction will aquire EXCLUSIVE lock (because of
> > the insert command) and it will keep this lock until commit, which
> > takes place after the last select and last semicolon.
> >
> > So i believe no other threads should be able to do anything with your
> > db until the whole query finishes.
> and from Kees Nuyt:
> > The last_insert_rowid() function returns the ROWID of the last row
> > insert from the database connection which invoked the function.
> > So, yes, it suffers from threads if the threads use the same
> > database connection.
> whom to trust?

  The docs, which make this fairly clear:


    The last_insert_rowid() function returns the ROWID of the last row
    insert from the database connection which invoked the function. The
    last_insert_rowid() SQL function is a wrapper around the
    sqlite3_last_insert_rowid() C/C++ interface function. 


    This routine returns the rowid of the most recent successful INSERT
    into the database from the database connection in the first
    argument. If no successful INSERTs have ever occurred on that
    database connection, zero is returned.

  So Kees Nuyt is correct... the value returned by last_insert_rowid()
  is "per database connection".  It is not a global.  It is not a
  per-database-file value.  It is not a pre-thread value.
  If each thread is using its own, private database connection, then
  you're safe.  If multiple threads are sharing a database connection
  and using the "serialized" thread mode, then you have a race
  condition as it is possible for the database connection to be
  handed off between statements.  The value returned by
  last_insert_rowid() may be invalid by the time it is called.

  In either case, these two operations are never "atomic", in the
  fullest sense of that word.  last_insert_rowid() is not bounded by
  transactions in the way statement processing is.

> as for Kees Nuyt reply, did you toke int account that "select 
> last_insert_rowid() "
> and insert query combined in single query and executed via single call 
> of sqlite3_exec()?

  Using sqlite3_exec() changes nothing.  It just runs the normal
  prepare/step interfaces.  It does not provide any kind of atomic
  processing above and beyond autocommit.  It doesn't even wrap
  multiple statements in a transaction.  It is just a syntax
  short-cut and provides no significant functionality beyond


Jay A. Kreibich < J A Y  @  K R E I B I.C H >

"Intelligence is like underwear: it is important that you have it,
 but showing it to the wrong people has the tendency to make them
 feel uncomfortable." -- Angela Johnson
sqlite-users mailing list

Reply via email to