Closed MarinPostma closed 1 year ago
That's a relatively fix I think, we just have to check that we haven't timed out the current transaction in the connection. For checkpointing, we can also have it steal the lock when necessary. I'll do that :) @psarna
Btw, our checkpointing connection is not preemptible, since it needs to finish, right? In that case we should clearly log and measure how much time a checkpoint takes, since it's likely to be a source of SQLITE_BUSY for users
This is an argument for checkpointing often
In that case, we should clearly log and measure
we already do that :)
Looks good, ship it, @MarinPostma! 🚀
This PR removes the need to spawn long-lasting threads for libsql connections. This reduces the number of threads required by sqld, since it can now reuse threads from the thread pool for connections.
Lock stealing
Previously, every connection spawned a blocking thread that kept track of the transaction state and timed out and rolled if a transaction didn't complete in time.
Avoiding to spawn a new thread means that we need a new mechanism to timeout a transaction. This PR introduces a lock-stealing mechanism. The lock-stealing algorithm only monitors write locks, meaning RO transactions can continue indefinitely. Another change is that a lock is stolen i.if another connection claims it. Therefore, a write connection can go indefinitely until another connection steals the lock, guaranteeing it had at least TXN_TIMEOUT_DURATION to perform work.
Here is a detailed description of the algorithm:
TxnState
, that contains aTxnSlot
TxnSlot
is placed in theTxnState
shared with other connections to this database, while another clone is kept in the transaction state. The TxnSlot contains the instant the txn should timeout, ais_stolen
flag, and a pointer to the connection currently holding the lock.busy_handler
callback will be called. The callback is being passed to theTxnState
for the connection. The handler looks at the current slot to determine when the current txn will timeout and waits for that instant before retrying. The waiting handler can also be notified that the transaction has been finished early.