On Thu, Aug 19, 2010 at 07:54:19PM +0100, Simon Slavin scratched on the wall:

>  I don't know what you mean by 'cursor'.  SQLite has commands.  You
> execute one command at a time.  Even a command like a SELECT that
> gathers lots of data gathers the data all in one go, then finishes.  

  None of this is true for the API.  You are more than able to have
  multiple statements "in flight" at the same time (I don't mean
  "prepared", I mean actually executing).  SELECT does not give the data
  in one go, but returns it one row at a time.  You can have calls to
  sqlite3_step() that reference multiple statements inter-mixed with
  each other.

> SQLite does not mark its place with one command, then return to that
> place again with another command.  

  Actually, that is *exactly* what prepared statements do each time you
  call sqlite3_step().

> SQLite never locks individual
> records, it only every locks the entire database file in various ways.

  OK, that's almost true.

> > - Is there a way to prevent SQLite from keeping the SHARED lock
> >   while waiting for an EXCLUSIVE lock if doing so would result in a
> >   deadlock (because another connection holding a SHARED lock needs to
> >   get an EXCLUSIVE lock before it can release the SHARED lock)?
> 
> SQLite will never know about an impending deadlock,

  You can't jump directly to the EXCLUSIVE lock, there are steps.

  But, yes, SQLite auto-detects this dead-lock situation and has the
  connection that does not already have the write lock return an
  SQLITE_BUSY, even if there is an busy-handler in place.  It is up to
  the application to do the right thing, however.

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

     The presence of a busy handler does not guarantee that it will be
     invoked when there is lock contention. If SQLite determines that
     invoking the busy handler could result in a deadlock, it will go
     ahead and return SQLITE_BUSY or SQLITE_IOERR_BLOCKED instead of
     invoking the busy handler. Consider a scenario where one process
     is holding a read lock that it is trying to promote to a reserved
     lock and a second process is holding a reserved lock that it is
     trying to promote to an exclusive lock. The first process cannot
     proceed because it is blocked by the second and the second process
     cannot proceed because it is blocked by the first. If both
     processes invoke the busy handlers, neither will make any
     progress. Therefore, SQLite returns SQLITE_BUSY for the first
     process, hoping that this will induce the first process to release
     its read lock and allow the second process to proceed.

  In short, you always need to deal with SQLITE_BUSY errors by, sooner
  or later, backing off and rolling back the current transaction (which
  should also release all the locks).  SQLite puts this responsibility
  in the hands of the application, however...  SQLite will let the
  application know there is a problem, but it is up to the application
  to fix it.  If you do not respond to a SQLITE_BUSY error, the 
  connections can remain dead-locked.

  This should never happen between statements using the same
  connection, however... the locks belong to the connection, not the
  statements, so two statements using the same connection can never
  deadlock.

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

Reply via email to