Home » Android » SQlite transactions: change visibility

SQlite transactions: change visibility

Posted by: admin November 1, 2017 Leave a comment

Questions:

I know transactions are supposed to enforce ACID properties but w.r.t transaction in SQLite, a guy here warns about the transaction done on same connection to be visible to others:

By default — changes that are being done in a transaction on a single
SQLite database connection can be visible to other transactions on
that connection immediately — even before calling
SQLiteDatabase.endTransaction()

which is on Medium and since no one has pointed out, seems to be authentic advice.

Now, I was reading about enableWriteAheadLogging() as a solution for concurrent Db access from official docs and found this:

This method enables parallel execution of queries from multiple
threads on the same database. It does this by opening multiple
connections to the database and using a different database connection
for each query. The database journal mode is also changed to enable
writes to proceed concurrently with reads.

When write-ahead logging is not enabled (the default), it is not possible for reads and writes to occur on the database at the same
time. Before modifying the database, the writer implicitly acquires an
exclusive lock on the database which prevents readers from accessing
the database until the write is completed.

In contrast, when
write-ahead logging is enabled (by calling this method), write
operations occur in a separate log file which allows reads to proceed
concurrently. While a write is in progress, readers on other threads
will perceive the state of the database as it was before the write
began. When the write completes, readers on other threads will then
perceive the new state of the database.

Now, if you read the highlighted part above, you see that by default, without enabling write ahead logging, the default behavior prevents concurrent read/write access and blocks until current operation has completed. If you contrast this with what the gut above said, it seems that with transaction, there is no such blocking.

How can this be possible that non-transactional behavior prevents you from reading or writing to the Db but the transactional one does?

Answers:

There is no “non-transactional behaviour“:

No changes can be made to the database except within a transaction. Any command that changes the database (basically, any SQL command other than SELECT) will automatically start a transaction if one is not already in effect. Automatically started transactions are committed when the last query finishes.


What that guy says is technically wrong; there are no “other transactions on that connection”.
A connection can have only one active transaction at the same time.

When multiple threads share the same connection, they share the transaction.
And because they are in the same transaction, they are not isolated from each other. Any thread that executes a BEGIN/COMMIT/ROLLBACK, or any other SQL statement, affects all other threads on the same connection.

Questions:
Answers:

By default — changes that are being done in a transaction on a single
SQLite database connection can be visible to other transactions on
that connection immediately — even before calling
SQLiteDatabase.endTransaction()

You may be READING (pun intentional) more into what has been said. i.e. The changes applied will be available i.e. they can be SEEN/READ within the connection BUT they have not been written/committed.

It’s only when/if

  • a) the outer AND ALL inner/nested transactions have been marked as clean/OK by a setTransactionSucccessful AND

  • b) the endTransaction is invoked

that the changes are committed (written to disk). i.e. it is only at/during the END that data is written to disk.