Updating in-process connections on write
I'm using the node-sqlite3 library in my program and I'm opening 2 connections to the same DB file in the same process, one read-only (RO) and the other for transacting (RW).
I'm doing this so that reads from the application don't see intermediate values during transactions, but maybe that's misguided. In any case it seems easier than wrapping everything in read transactions.
The problem I'm having is that sometimes, after completing a write transaction, the RO connection doesn't "see" the change. I would have expected connections from the same process to notify one another.
As a workaround, I'm setting pragma user_version in the transaction and then polling the RO connection (using a prepared query) until it sees the same user_version.
Is there a better way to do this?
(2) By Gunter Hick (gunter_hick) on 2021-10-08 11:44:34 in reply to 1 [link] [source]
Sharing a connection between threads that use implicit transactions means that none of the threads can be sure when a transaction begins or ends. They share a common transaction that begins when any thread starts reading and ends when all threads are done with reading simultaneously. This is not transparent to the individual threads. E.g. if two threads alternate in reading, each starting a new SELECT before the other one ends it's SELECT, the transaction never commits, and thus never sees the result of a write transaction on the other connection. Using a separate connection for each thread gives each thread control over it's own transaction. No transaction can see "intermediate" values if you properly BEGIN and END any write transactions.
Ok thank you, that validates me using two connections.
My writes are multi-step affairs (from event sourcing processing) so the transactions should be hidden from reads.
Yes, the latter, I pass
I wish there was something like
PRAGMA really_check_for_change :)
PRAGMA data_version' https://sqlite.org/pragma.html#pragma_data_version
However, the data_version will not change if the request is not made when no transaction is in progress on that connection, even if a change was previously committed on another connection.
I'll set up a test rig and experiment. Possibly just reading data_version might be enough then.
The problem I'm having is that sometimes, after completing a write transaction, the RO connection doesn't "see" the change.
That is correct. WHen using the WAL journal mode, a connection will not "see" any changes made to the database on a different connection until the specific sequence (1) commits, either implicitly or explicitly, the changes; and then (2) the original connection (the one that you want to see the changes) must BEGIN A TRANSACTION, either explicitly or implicitly, in order to see the changes to the database made on the other connection.
This means that, for a connection, if the following holds:
- sqlite3_txn_state returns 0 https://sqlite.org/c3ref/txn_state.html
Then a SELECT issued against that connection will "see" all changes committed to the database BEFORE the above condition was tested.
((Actually, that would be all changes committed before the statement which starts the transaction, not from the time the condition was tested.))