Is there a good practice /setting for such high rate of concurrent writes
with reads ?
I understand that multiple readers with single writer at any time t is the
model which sqlite has with various locks/states (unlocked, pending , shared
, reserved , exclusive).

"with" is a bit unclear.

To clarify, unless you're using WAL mode, there in no actual concurrency in SQLite.
Quoting Richard Hipp who recently wrote:

(1) You only have to set WAL mode once for the database. The database
remembers that it is in WAL mode and all subsequent opens bring it back up
in WAL mode again (until you deliberately change it out of WAL mode.) You
do *not* have to set WAL mode every time you open the database file.

(2) WAL really does give better concurrency since it allows other processes
to continue reading while a single process is writing to the database. In
rollback mode you can have one writer *or* multiple readers. In WAL mode
you can have one writer *and* multiple readers. On a busy system, or in a
system with long-running transactions, the difference can be significant.

(3) Transactions commit a lot faster with WAL. Depending on your app, you
might see a measurable performance improvement just by switching to WAL.

(4) WAL mode is much more resistant to corruption following a power failure
that occurs soon after the disk drive lied and said that content was
committed to oxide when in fact it was still in a volatile track buffer.
And pretty much all consumer-grade disk drives tell such lies these days.

The part relevant to you is in (2).
  rollback mode: 1 writer OR  many readers
  WAL mode:      1 writer AND many readers

Will a busy_timeout setting for all connections and making write
transactions as "begin immediate"  handle the situation ?

Yes, try using the same timeout for _all_ conections and always use IMMEDIATE transactions for RMW (Read Modify Write) SQL blocks, just BEGIN for read-only SQL blocks and autocommit for stand-alone statements.

You have to decide on the value of the timeout, and the ideal value in rollback mode is NOT the time it takes for the worst case transaction plus some margin.

To see why look at how SQLite behaves when your transaction (A) is locked by a blocking transaction (B): it retries internally a certain number of times for a short period, then puts (A) to sleep for a while. During this short sleep (B) may terminate and another blocking transaction (C) may proceed. When (A) gets out of sleep it still sees the DB locked (this time by (C) not by (B) but noone notices). This ends with either: the longest sequence of the worst-case transactions terminates and your (A) proceeds normally OR your timeout expires and you get "DB locked".

WAL dramatically simplifies this that since readers can by concurrent to one writer: the right timeout is actually the worst-case write transaction plus some margin.

I've been using this setup (with 10 minutes timeout, that's close to forever!) for years in my business-type applications and never got any issue. (I'm currently switching to WAL mode.)

Please someone corrects me if this doesn't reflect SQLite current behavior anymore.
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to