When a stress thread runs out of work, execute COMMIT and ignore the
result.
This prevents the currently extremely common scenario where:
- Thread x does BEGIN
- Thread x does e.g. INSERT ...
Then runs out of iterations and stops. No other threads can write
anything and they just wait for 5 seconds (busy timeout) and then try
again, forever.
Closes#3697Closes#3762
Without this change and running:
```
cd stress
while cargo run -- --nr-threads=4 -i 1000 --verbose --busy-timeout=0; do; done
```
I can produce a deadlock quite reliably.
With this change, I can't.
Even with 5 second busy timeout (the default), the run makes progress
although it is slow as hell because of the busy timeout.
Full disclosure: i couldn't figure out based on parking lot RwLock
semantics why this would fix it, so maybe it just lessens the
probability
Reviewed-by: Preston Thorpe <preston@turso.tech>
Closes#3759
When a stress thread runs out of work, execute COMMIT and ignore
the result.
This prevents the currently extremely common scenario where:
- Thread x does BEGIN
- Thread x does e.g. INSERT ...
Then runs out of iterations and stops. No other threads can write
anything and they just wait for 5 seconds (busy timeout) and then
try again, forever.
Without this change and running:
```
cd stress
cargo run -- --nr-threads=4 -i 1000 --verbose --busy-timeout=0
```
I can produce a deadlock quite reliably.
With this change, I can't.
Even with 5 second busy timeout (the default), the run makes progress although it is slow as hell because of the busy timeout.
Closes#3748
Right now if any error happens during an interactive tx that causes the
`Transaction` to drop, the program will panic.
To prevent this, we store the `DropBehavior` of the transaction on the
`Connection` when it drops and issue the corresponding action (ROLLBACK
/ COMMIT / IGNORE / PANIC) the next time `Connection` is used to access
the database. This defaults to `IGNORE`.
I don't know how good this solution is, but we can at least prevent a
panic by storing whether the connection has a dangling transaction and
roll it back automatically the next time the connection tries to do
something.
Reviewed-by: Preston Thorpe <preston@turso.tech>
Closes#3750
Rolling back a transaction on Error should result in
`connection.auto_commit` being set back to true.
Added a regression test for this where a UNIQUE constraint violation
rolls back the transaction and trying to COMMIT will fail.
Currently, our default conflict resolution strategy is ROLLBACK, which
ends the transaction. In SQLite, the default is ABORT, which rolls back
the current statement but allows the transaction to continue.
We should migrate to default ABORT once we support subtransactions.
Closes#3746
Reviewed-by: Preston Thorpe <preston@turso.tech>
Closes#3747
Closes#3748
Right now if any error happens during an interactive tx that causes the
`Transaction` to drop, the program will panic.
I don't know how good this solution is, but we can at least prevent a panic
by storing whether the connection has a dangling transaction and roll it back
automatically the next time the connection tries to do something.
This patch pushes unsafe Send and Sync to individual components instead
of doing it at Database level. This makes it easier for us to
incrementally fix thread-safety, but avoid developers adding more thread
unsafe code.
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#3745
`INSERT OR IGNORE INTO t VALUES (...)` can trivially be rewritten to
`INSERT INTO t VALUES (..) ON CONFLICT DO NOTHING`
This PR does this rewriting, as well as finishes a large refactor on
INSERT translation in general.. I just need a break from the rest of
this feature tbh.. just was getting under my skin and I have been in
`translate` land for too long.
Closes#3742
Rolling back a transaction should result in `connection.auto_commit` being set
back to true.
Added a regression test for this where a UNIQUE constraint violation rolls back
the transaction and trying to COMMIT will fail.
Currently, our default conflict resolution strategy is ROLLBACK,
which ends the transaction. In SQLite, the default is ABORT, which rolls back
the current statement but allows the transaction to continue.
We should migrate to default ABORT once we support subtransactions.
This patch pushes unsafe Send and Sync to individual components instead
of doing it at Database level. This makes it easier for us to
incrementally fix thread-safety, but avoid developers adding more thread
unsafe code.