Commit Graph

314 Commits

Author SHA1 Message Date
Pekka Enberg
65b382b9e1 Merge 'Make MVCC code Send and Sync' from Pekka Enberg
Closes #3361
2025-09-27 08:21:01 +03:00
Pekka Enberg
a932ac5450 Merge 'core: recover logical log on Database::connect ' from Pere Diaz Bou
If we open database and logical log is not empty we need to recover from
it. We also make sure a single recover executes concurrently and other
connections just wait for it to finish.
I also changed the fuzz tester to use `restart` instead of calling
`load_logical_log` manually to test this behaviour.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #3359
2025-09-27 08:20:41 +03:00
Pere Diaz Bou
99adf73168 core/mvcc/logical-log: rename to needs_recovery 2025-09-26 16:59:57 +02:00
Pere Diaz Bou
9e47cc3700 clippy 2025-09-26 14:16:11 +02:00
Pekka Enberg
1402e9841e core/mvcc: Wrap StreamingLogicalLogReader::buffer with RwLock 2025-09-26 14:19:16 +03:00
Pekka Enberg
96accef06c core/mvcc: Wrap header with RwLock 2025-09-26 14:10:18 +03:00
Pere Diaz Bou
9c1d94a355 core/mvcc/logical-log: assert we don't call begin_load_tx twice 2025-09-26 12:59:13 +02:00
Pere Diaz Bou
4cdf293a2b core/mvcc/logical-log: fuzz test recover use db.restart 2025-09-26 12:56:58 +02:00
Pere Diaz Bou
ae994146af core/mvcc/logical-log: on mvcc restart clear DATABASE_MANAGER 2025-09-26 12:56:43 +02:00
Pere Diaz Bou
83d8a7c775 core/mvcc/logical-log: lock recover logical log process 2025-09-26 12:47:31 +02:00
Pekka Enberg
27ee12b300 Merge 'core/mvcc/logical-log: refactor get log path in tests' from Pere Diaz Bou
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #3346
2025-09-25 21:04:15 +03:00
Pekka Enberg
9c9b525f8a Merge 'core: Wrap Connection::mv_tx with RwLock' from Pekka Enberg
Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>

Closes #3332
2025-09-25 20:47:03 +03:00
Pere Diaz Bou
334da8abbb core/mvcc/logical-log: refactor get log path in tests 2025-09-25 18:33:26 +02:00
Jussi Saurio
c07a227560 Merge 'core/mvcc/logical-log: load logical log from disk' from Pere Diaz Bou
## Description
Read transactions from logical log and load mvcc store based on the
contents onto transaction 0, which is the special transaction where we
will load all row versions that can be read by all new transactions.
## Todo
- [x] Testing for multiple transactions
- [ ] Lock multiple loading of same logical-log at the same time
- [x] Add column_count to format because if not it is hard to judge from
record alone.
- [x] Trim buffer read
I was thinking to implement the rest on another pr to not increase load
to review this one.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #3323
2025-09-25 16:26:34 +03:00
Pere Diaz Bou
8f3332377a core/mvcc/logical-log: fmt fmt fmt fmt 2025-09-25 13:33:16 +02:00
Pere Diaz Bou
b75eb9f09d core/mvcc/logical-log: drain consumed bytes on read_more_data 2025-09-25 13:31:03 +02:00
Pere Diaz Bou
7b131b0b0d core/mvcc/logical-log: test fuzz logical log read 2025-09-25 13:23:43 +02:00
Pere Diaz Bou
dd0a71484d core/mvcc/logical-log: test insert 100 transactions 2025-09-25 12:40:05 +02:00
Pere Diaz Bou
8528f92248 core/mvcc/logical-log: fix is_eof 2025-09-25 12:39:48 +02:00
Pere Diaz Bou
654f9a9412 core/mvcc/logical-log: read column_count from immutable record 2025-09-25 12:27:30 +02:00
Pekka Enberg
fa1e986dca core: Wrap Connection::mv_tx with RwLock 2025-09-25 12:47:43 +03:00
Jussi Saurio
3d38c5a101 mvcc: disallow promote to exclusive tx if another tx committed in between 2025-09-25 11:50:09 +03:00
Jussi Saurio
7c86e7b9c4 merge conflicts with atomics PRs 2025-09-25 11:49:44 +03:00
Jussi Saurio
ede2a882f1 mvcc: revert connection schema changes in mv rollback 2025-09-25 08:43:00 +03:00
Jussi Saurio
1626ef046b mvcc: abort tx if other tx made a schema change in between 2025-09-25 08:43:00 +03:00
Jussi Saurio
864fa379dd mvcc: require exclusive transaction for schema changes 2025-09-25 08:42:59 +03:00
Jussi Saurio
49602f409f fixes after atomics merge conflicts 2025-09-25 08:16:52 +03:00
Jussi Saurio
3010dc0255 mvcc: add CheckpointStateMachine
performs a blocking, truncating checkpoint:

- when started, blocks any other transactions from starting
- writes all row versions to pager that havent already been
  checkpointed
- flushes them to wal
- checkpoints wal to db

in the case of added/deleted rows in table id 1 (sqlite schema),
also creates/destroys btrees accordingly
2025-09-25 08:12:13 +03:00
Jussi Saurio
429f305fe8 mvcc: add MvStore::get_next_table_id()
this assigns "synthetic" root page numbers instead of using the pager
or btree cursors to allocate pages. Actual page allocation will only
happen during checkpoint, since regular MVCC commit bypasses the
pager.
2025-09-25 08:12:13 +03:00
Jussi Saurio
b702af8ac0 mvcc: add truncate method to logical log 2025-09-25 08:12:13 +03:00
Jussi Saurio
8f33b31c3d mvcc: update global header on commit end 2025-09-25 08:12:13 +03:00
Jussi Saurio
7464d1c172 mvcc: remove tx from store when commit write set is empty
previously, this was leaking transaction IDs in the mv store.
2025-09-25 08:12:13 +03:00
Jussi Saurio
949e6dd728 mvcc: remove unused states and fields from CommitStateMachine
none of the pager commit related data and logic are used anymore,
so let's delete them.
2025-09-25 08:12:12 +03:00
Pere Diaz Bou
1478538cb9 core/mvcc/logical-log: load logical log from disk
Read transactions from logical log and load mvcc store based on the
contents onto transaction 0, which is the special transaction where we
will load all row versions that can be read by all new transactions.

- [ ] Testing for multiple transactions
- [ ] Lock multiple loading of same logical-log at the same time
- [ ] Add column_count to format because if not it is hard to judge from
record alone.
2025-09-25 02:15:28 +02:00
Pere Diaz Bou
74f0830920 Merge 'core/mvcc/logical-log: on disk format for logical log' from Pere Diaz Bou
This format is based on previous discussions:
1. Log header
```rust
/// Log's Header, this will be the 64 bytes in any logical log file.
/// Log header is 64 bytes at maximum, fields added must not exceed that size. If it doesn't exceed
/// it, any bytes missing will be padded with zeroes.
struct LogHeader {
    version: u8,
    salt: u64,
    encrypted: u8, // 0 is no
}
```
2. Transaction format:
* Transaction id
* Checksum u64
* Byte size of all rows combined
* Rows
* End marker (offset position after appending buffer)
3. Row format:
```rust
    /// Serialize a row_version into on disk format.
    /// Format of a "row" (maybe we could change the name because row is not general enough for
    /// future type of values):
    ///
    /// * table_id (root page) -> u64
    /// * row type -> u8
    ///
    /// (by row type)
    /// Delete:
    /// * Payload length -> u64
    /// * Rowid -> varint
    ///
    /// Insert:
    /// * Payload length -> u64
    /// * Data size -> varint
    /// * Rowid -> varint
    /// * Data -> [u8] (data size length)
    fn serialize(&self, buffer: &mut Vec<u8>, row_version: &RowVersion) {

```

Closes #3245
2025-09-25 00:39:03 +02:00
Pekka Enberg
b590b353eb core/mvcc: Wrap Transaction::database_header with RwLock 2025-09-24 15:19:00 +03:00
Pekka Enberg
f5d3962459 core: Wrap Connection::transaction_state with RwLock 2025-09-23 14:01:31 +03:00
Pekka Enberg
b94aa22499 core: Wrap Connection::schema in RwLock 2025-09-23 10:31:20 +03:00
Pekka Enberg
b857f94fe4 Merge 'core: Wrap Connection::pager in RwLock' from Pekka Enberg
Closes #3247
2025-09-23 07:29:09 +03:00
Pekka Enberg
aa454a6637 core: Wrap Connection::pager in RwLock 2025-09-22 17:02:08 +03:00
Jussi Saurio
4af49ef98c mvcc: simplify StateMachine
TransitionResult is an internal implementation detail that tells
an invocation of StateMachine::step() to continue looping, but it
is of no use to other callers.

For this reason, just return an IOResult from StateMachine::step()
which simplifies the result handling.
2025-09-22 16:37:31 +03:00
Pere Diaz Bou
2f4426fc33 core/mvcc/logical-log: change order of Data size in InsertRow 2025-09-22 13:25:46 +02:00
Pere Diaz Bou
4cc88ee2bb core/mvcc/logical-log: rename Insert and Delete -> InsertRow and DeleteRow in LogRecordType 2025-09-22 13:21:54 +02:00
Pere Diaz Bou
db326affc6 core/mvcc/logical-log: rename LogRowType to LogRecordType 2025-09-22 13:19:02 +02:00
Pere Diaz Bou
e22a3893d5 core/mvcc/logical-log: remove column_count from insert row type 2025-09-22 13:18:17 +02:00
Pere Diaz Bou
4c959e760b core/mvcc/logical-log: add rows size field for transaction format 2025-09-22 13:15:07 +02:00
Pere Diaz Bou
2cd1562966 core/mvcc/logical-log: add format for transaction fields and marker end 2025-09-22 13:06:11 +02:00
Pere Diaz Bou
6fc1bed187 core/mvcc/logical-log: add format for logical log header 2025-09-22 13:00:52 +02:00
Pere Diaz Bou
36a728d984 core/mvcc/logical-log: add format for row types 2025-09-22 12:43:54 +02:00
Jussi Saurio
6a20735fe0 mvcc: add blocking checkpoint lock
MVCC checkpoints are always TRUNCATE, plus they block all other transactions.
This guarantees that never need to let transactions read from the SQLite WAL.

In MVCC, the checkpoint procedure is roughly as follows:
- Take the blocking_checkpoint_lock
- Write everything in the logical log to the pager, and from there commit to the SQLite WAL.
- Immediately TRUNCATE checkpoint the WAL into the database file.
- Release the blocking_checkpoint_lock.
2025-09-22 12:40:19 +03:00