My first surprise was SQLITE_BUSY_SNAPSHOT from BEGIN IMMEDIATE (see
?SQLITE_BUSY_SNAPSHOT from BEGIN IMMEDIATE?).  I have found another
source of such snapshot failures with WAL-mode databases.

I like to pre-compile my DML statements before starting transactions,
mainly for the implied syntax check.  (But perhaps there are also
performance benefits, too?I haven't checked.)

Here is what I did (if my tracing is correct).  Unless mentioned
otherwise, the operations succeed with SQLITE_OK.

  Open the database.
  Compile the UPDATE statement.
  Compile the ROLLBACK statement (used below).
  Start a BEGIN DEFERRED transaction (with a fresh statement).
  Reset the UPDATE statement.
  Step the UPDATE statement.
   -> this fails with SQLITE_BUSY_SNAPSHOT
  Reset/step/reset the pre-compiled ROLLBACK statement.
  Start a BEGIN IMMEDIATE transaction (with a fresh statement).
   -> this fails with SQLITE_BUSY_SNAPSHOT
  Start a BEGIN IMMEDIATE transaction (with a fresh statement).
  Reset the UPDATE statement.
   -> this fails with SQLITE_BUSY_SNAPSHOT

After the last failure, iterating through the list of stattements does
not show that the UPDATE statement is busy.

This seems to contradict this piece of the documentation:

| If X starts a transaction that will initially only read but X knows
| it will eventually want to write and does not want to be troubled
| with possible SQLITE_BUSY_SNAPSHOT errors that arise because another
| connection jumped ahead of it in line, then X can issue BEGIN
| IMMEDIATE to start its transaction instead of just an ordinary
| BEGIN. The BEGIN IMMEDIATE command goes ahead and starts a write
| transaction, and thus blocks all other writers. If the BEGIN
| IMMEDIATE operation succeeds, then no subsequent operations in that
| transaction will ever fail with an SQLITE_BUSY error.

<https://www.sqlite.org/isolation.html>

This happens with version 3.8.11.1 on Fedora 22.

I don't know how risky pre-compiling UPDATE statement is.  For SELECT
statements, it is problematic because they can lead to persistent
transaction failures with SQLITE_BUSY_SNAPSHOT because the
pre-compiled and partitial executed statement is busy and will block
creating a new transaction.  I wonder if this can happen with UPDATE
statements as well.

Reply via email to