I was thinking about this again, and I think there’s a far easier to implement way of doing this? One could just refresh the read version of the long-running transaction, at the cost of making a resolver do much more work over time:
- Every ~1s, create a new transaction
a) Set the new transaction to have the same read version as the ongoing transaction
b) Copy only the read conflicts from the ongoing transaction to the new transaction - Commit this new transaction.
a) If this new transaction commits, then that means none of the read values were changed. Update the read version of the ongoing transaction to the commit version of the new transaction.
b) If the new transaction aborted, abort the ongoing transaction. - Repeat until the long-running transaction is committed.
It’s not quite this simple, because there’s some complications here about what to do when a get()
is concurrently issued while the transaction to refresh the long-running transaction’s read version is running, but this seems like less overhead than maintaining an index of concurrency control in the database.