Re: [sqlite] threads and last_insert_rowid()

2010-11-19 Thread Jay A. Kreibich
On Tue, Nov 16, 2010 at 09:35:21AM -0500, Pavel Ivanov scratched on the wall:

> But as I see in SQLite sources sqlite3_exec does acquire
> connection's mutex, so nothing can be executed in between statements.
> Thus if you execute this line as one call to sqlite3_exec then it
> won't suffer from threading.

  Humm... I missed that.  I knew that _exec() doesn't actually open a
  proper transaction (since it has no idea what the transaction state
  might be), but I didn't catch that it still grabs the mutex to
  prevent issues with threads.
  
  Clever.



  More teo the point, that means a single _exec() call with the INSERT,
  followed by a call to last_insert_rowid() should always do the right
  thing.

   -j

-- 
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
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-18 Thread Jay A. Kreibich
On Tue, Nov 16, 2010 at 04:08:16PM +0300, Ruslan Mullakhmetov scratched on the 
wall:
>   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:

  http://sqlite.org/lang_corefunc.html#last_insert_rowid

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. 

  http://sqlite.org/c3ref/last_insert_rowid.html

[...]
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
  convenience.

   -j

-- 
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
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-16 Thread Richard Hipp
On Tue, Nov 16, 2010 at 11:38 AM, Ruslan Mullakhmetov <
r.mullakhme...@tools4brokers.com> wrote:

> > Understand this:  Any programming language that is built around threads
> is
> > inherently broken and should be avoided.  (I will not name names - you
> know
> > the languages I'm talking about.)  And any operating system that depends
> > upon threads for performance is equality busted and should also be
> shunned.
>
> so you advise to change language? to some functional or logic? i got no
> more
> idea how to avoid threads and evils connected with them.
>
> unfortunately i'm not free in language choosing cause i develop extensions
> which has api in language  that "is inherently broken and should be
> avoided".
>


I recognize this sad reality, which is why SQLite is "threadsafe" even
though we actively discourage the use of threads.  Sometimes you just have
no choice.  Unchangeable external constraints impose a programming language
or platform on you.  And for those occasions, you just have to VERY VERY
CAREFUL.



>
> > ___
> > 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
>



-- 
D. Richard Hipp
d...@sqlite.org
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-16 Thread Ruslan Mullakhmetov
> Understand this:  Any programming language that is built around threads is
> inherently broken and should be avoided.  (I will not name names - you know
> the languages I'm talking about.)  And any operating system that depends
> upon threads for performance is equality busted and should also be shunned.

so you advise to change language? to some functional or logic? i got no more
idea how to avoid threads and evils connected with them.

unfortunately i'm not free in language choosing cause i develop extensions
which has api in language  that "is inherently broken and should be avoided".

> ___
> 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


Re: [sqlite] threads and last_insert_rowid()

2010-11-16 Thread Richard Hipp
On Tue, Nov 16, 2010 at 10:29 AM, Ruslan Mullakhmetov <
r.mullakhme...@tools4brokers.com> wrote:

>
> as you see in _serialized_ mode "SQLite can be safely used by multiple
> threads with no restriction".
>
> do i misunderstand something?
>

With serialized threading, SQLite is perfectly "safe" to use.  But if you
change a value (the last-insert-rowid in this case) then that change will
appear in other threads.  There is nothing "unsafe" about that - you just
need to be aware that it happens.  "Safe" does not mean "atomic".

If nothing else, this entire discussion should make it abundantly clear that
threads are a very dangerous construct and should be actively avoided in all
software that strives to be robust and/or reliable.  People rant and rail
about the evils of "goto" or pointers, and to be fair, those constructs are
easily misused.  But threads are a far more insidious evil in that they are
non-deterministic:  the failures happen differently on each run, or perhaps
not at all until the product goes into production.

Understand this:  Any programming language that is built around threads is
inherently broken and should be avoided.  (I will not name names - you know
the languages I'm talking about.)  And any operating system that depends
upon threads for performance is equality busted and should also be shunned.

"Threadsafe" is an oxymoron.  Nothing is safe when threads are in play.
There are merely differing levels of hazard.

So the best solution to your problem, Ruslan, is to not use threads.
Failing that, allocate a separate database connection for each thread.  If
you can't do that, then you are going to have concurrency issues to deal
with, regardless of what libraries you use.

-- 
D. Richard Hipp
d...@sqlite.org
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-16 Thread Ruslan Mullakhmetov
thanks everybody, especially Pavel Ivanov who did not give himself a 
trouble to look at the source though i did.

but as far as i understand this is only applicable to current version of 
sqlite and future releases may change things.

Jay A. Kreibich wrote:

 >   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.

Yes, i share one database handle between multiple threads. actually i 
have some class Storage which is accessible from multiple threads.
I defined SQLITE_TREADSAFE and thought that there could be no racing.

as for http://cvs.hwaci.com/threadsafe.html

 > SQLite support three different threading modes:
 >
 >   1. Single-thread. In this mode, all mutexes are disabled and SQLite 
is unsafe to use in more than a single thread at once.
 >   2. Multi-thread. In this mode, SQLite can be safely used by 
multiple threads provided that no single database connection is used 
simultaneously in two or more threads.
 >   3. Serialized. In serialized mode, SQLite can be safely used by 
multiple threads with no restriction.

as you see in _serialized_ mode "SQLite can be safely used by multiple 
threads with no restriction".

do i misunderstand something?

BR, RM
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-16 Thread Pavel Ivanov
> whom to trust?

Trust Kees. Borgan's thought about keeping the lock and transaction
management inside sqlite3_exec is incorrect.

> 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()?

Actually it depends on particular implementation of sqlite3_exec.
Kees' reply is general and it would stand if sqlite3_exec didn't
acquire connection's mutex and let individual statements acquire mutex
as necessary. But as I see in SQLite sources sqlite3_exec does acquire
connection's mutex, so nothing can be executed in between statements.
Thus if you execute this line as one call to sqlite3_exec then it
won't suffer from threading.


Pavel

On Tue, Nov 16, 2010 at 8:08 AM, Ruslan Mullakhmetov
 wrote:
>  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?
>
> 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()?
>
> BR, RM
> ___
> 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


Re: [sqlite] threads and last_insert_rowid()

2010-11-16 Thread Ruslan Mullakhmetov
  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?

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()?

BR, RM
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-15 Thread Roger Binns
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 11/15/2010 04:15 AM, Ruslan Mullakhmetov wrote:
> i need to get last insert id in multithreaded app.
> I use C API, actually some C++ wrap over it.
> 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?

As others mentioned the value returned is for the database handle.  There
are two ways you can address this.  One is to make each thread use its own
completely separate database handle.  Do some benchmarking if you think it
will affect overall performance of your program (unlikely) and you can do
some tuning such as shared cache mode.

The other thing is to use a transaction.  I do queries like this:

  begin;
insert into tbl( filed ) VALUES ( 1 );
Select last_insert_rowid() as li;
  commit;

Another issue you need to be careful with when threading is errors as the
SQLite error stuff is not thread safe.  SQLite records the error message
pointer against the database handle and the error API returns this pointer.
 Another thread could cause  different error code/message by the time you
get their values.  Also the pointer the API returns could become invalid by
the time you use it due to other thread activity, with the worst case being
that you crash if it now points to unmapped memory.

You need to structure your calls to SQLite APIs like this:

  sqlite3_mutex_enter(sqlite3_db_mutex(db));
  rc=sqlite3_...;
  if (rc!=SQLITE && rc!=SQLITE_DONE && rc!=SQLITE_ROW)
{
copy sqlite3_errmsg(db) into a thread local buffer;
copy code as well if you don't use rc;
}
  sqlite3_mutex_leave(sqlite3_db_mutex(db));


On first discovering this issue several years ago I did campaign for the
SQLite semantics be changed so that the error code and string become thread
local just like errno and GetLastError are, but DRH didn't want to do this
because there *may* be code out using SQLite that does calls in one thread
and retrieves error information in a different one.

Roger
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkzhWQYACgkQmOOfHg372QSn+QCcC+PdUdjCrfny6fucvY5q1D8W
FIUAn1vAgsVDw+NESBbwsA8ST9mFIzVC
=a1CE
-END PGP SIGNATURE-
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-15 Thread Kees Nuyt
On Mon, 15 Nov 2010 15:15:10 +0300, Ruslan Mullakhmetov
 wrote:

>hi.
>
>i need to get last insert id in multithreaded app.
>I use C API, actually some C++ wrap over it.
>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?

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.
-- 
  (  Kees Nuyt
  )
c[_]
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] threads and last_insert_rowid()

2010-11-15 Thread Bogdan Pilch
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.

   bogdan

> hi.
> 
> i need to get last insert id in multithreaded app.
> I use C API, actually some C++ wrap over it.
> 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?
> 
> -- 
>   Ruslan Mullakhmetov
> ___
> 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


[sqlite] threads and last_insert_rowid()

2010-11-15 Thread Ruslan Mullakhmetov
hi.

i need to get last insert id in multithreaded app.
I use C API, actually some C++ wrap over it.
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?

-- 
  Ruslan Mullakhmetov
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users