Commit Graph

297 Commits

Author SHA1 Message Date
pedrocarlo
db005c81a0 add option to disable wal checkpoint 2025-07-03 12:04:17 -03:00
Pere Diaz Bou
5d856499c4 move update schema global on commit and not on rollback txn 2025-07-03 12:36:48 +02:00
Pere Diaz Bou
c799396c3d rollback schema in connection 2025-07-03 12:36:48 +02:00
Pere Diaz Bou
65a7fe13cf remove lock from private schema copy 2025-07-03 12:36:48 +02:00
Pere Diaz Bou
abf1699dd2 set scheam version and update shared schema in txn 2025-07-03 12:36:48 +02:00
KaguraMilet
aca08238d8 fix buffer pool is not thread safe problem 2025-07-01 16:06:55 +08:00
Pere Diaz Bou
486c4b69fb WAL record db_size frame on commit last frame
`db_size` is `>0` in case of last frame written of a transaction. This
is necessary as we need to know -- while recovering wal contents -- that
we have read a transaction fully instead of treating every frame as its
own transaction.
2025-06-27 16:21:48 +02:00
Pekka Enberg
5791ab9dff Merge 'Cache reserved_space and page_size values at Pager init to prevent doing redundant IO' from Krishna Vishal
### Problem
Profiling revealed that `usable_space()` calls were consuming 60% of
total execution time for simple SELECT queries, making Limbo
approximately `6x` slower than SQLite for SELECT operations.
The bottleneck was caused by `usable_space()` performing expensive I/O
operations on every call to read `page_size` and `reserved_space` from
the database header, despite `page_size` values being effectively
immutable after database initialization. Only `reserved_space` is
allowed to increase in SQLite.
Evidence: https://share.firefox.dev/44tCUIy
### Solution
Implemented OnceCell-based caching for both page_size and reserved_space
values in the Pager struct:
`page_size: OnceCell<u16>` - Page size is immutable after database
initialization per SQLite specification
`reserved_space: OnceCell<u8>` - Reserved space rarely changes and only
grows, safe to cache
### Performance Impact
Benchmark results: Simple SELECT query time reduced from ~2.89ms to
~1.29ms (~55% improvement)

Closes #1852
2025-06-27 16:40:14 +03:00
Pere Diaz Bou
8e0f8041ed properly set database header contents on initialization
After moving page1 write to be async I moved the contents update to
wrong place. This should fix it.
2025-06-27 11:44:11 +02:00
Krishna Vishal
cda1ab8d76 Use OnceCell instead of OnceLock. 2025-06-27 13:32:03 +05:30
Krishna Vishal
af2ab87810 Cache reserved_space and page_size values at Pager init.
We use `OnceLock` for this. TODO: Invalidate reserved_space when
we make functionality the to change it.
2025-06-27 12:51:11 +05:30
Pere Diaz Bou
aa93b70a96 empty -> unitialized 2025-06-26 17:59:23 +02:00
Pere Diaz Bou
4d80b8237d write page1 on database initialization
Page 1 must be initialized and written as soon as possible without
marking page as dirty.
2025-06-26 14:44:23 +02:00
Pekka Enberg
a48198ec60 Merge 'Rollback simple support' from Pere Diaz Bou
Support for simple interactive rollback like:
```sql
    create table t (x);
    insert into t values (1);
    begin;
    insert into t values (2);
    rollback;
    select * from t;
```
This PR also fixes some other issues I found while debugging:
* Checkpoint would never `clear_dirty` on pages in page cache.
* Auto commit for interactive transactions was not respected so any
`insert` after `begin` would flush frames regardless of `auto_commit`
state.
* `max_frame` on wal shared state was being updated after every
`append_frame` which was incorrect, as another transaction would be able
to use that new `max_frame` even tho the transaction could've rolled
back. Instead we update the private copy of `max_frame` and only update
it at the end.
Follow up for later are savepoints which require implementing a
subjournal to track savepoints and their modified pages.

Closes #1825
2025-06-25 20:02:09 +03:00
Pere Diaz Bou
c02337c8cc clear dirty pages on rollback 2025-06-25 14:01:53 +02:00
Pere Diaz Bou
a3ad138df8 checkpoint clear dirty page if it was on cache 2025-06-25 14:01:53 +02:00
Pere Diaz Bou
22f9cd695d commit_txn track rollback case 2025-06-25 14:00:57 +02:00
Pere Diaz Bou
bdd2010df3 autocommit rollback 2025-06-25 14:00:57 +02:00
Jussi Saurio
27b3ecf599 core/db&pager: fix locking for initializing empty database
When `struct Database` is constructed, store `is_empty` as an
`Arc<AtomicBool>` - the value is true if:

1. DB size is zero
2. WAL has no frames

When `struct Pager` is constructed, this `Arc` is simply cloned.
When any connection runs a transaction it will first check `is_empty`,
and if the DB is empty, it will lock `init_lock` and then check `is_empty`
again, and if it's still true, it allocates page1 and stores `false` in
the `is_empty` `AtomicBool` and drops the lock.

---

Note that Limbo can currently have a zero DB and a WAL with frames,
as we have no special logic for folding page1 to the main DB file
during initialization.

Page 1 allocation currently happens on the first transaction (read or
write, due to having to support `select * from sqlite_schema` on an
empty DB; we should really check how SQLite actually does this.).
2025-06-25 14:45:21 +03:00
Jussi Saurio
480f0a04b5 make clippy happy about mutating database_size immediately after default construction 2025-06-24 14:41:50 -03:00
Diego Reis
1921fcb943 Add comments to clarify current behaviour 2025-06-24 14:41:50 -03:00
Diego Reis
6ae196d7b3 Add mutex to allocating page1
This is to prevent race conditions where two threads could try to initialize database at the same time
2025-06-24 14:41:50 -03:00
Diego Reis
a1b7b3c6f6 Fix clippy complains 2025-06-24 14:41:50 -03:00
Jussi Saurio
a5d71a65be clippy doesnt get it 2025-06-24 14:41:50 -03:00
Jussi Saurio
133d498724 Implement a header_accessor module so that DatabaseHeader structs arent initialized on every access 2025-06-24 14:41:50 -03:00
Jussi Saurio
ad20e306f7 dont panic on cache clear error 2025-06-24 14:41:50 -03:00
Jussi Saurio
ba3bfa058d Delete unused stuff 2025-06-24 14:41:50 -03:00
Jussi Saurio
6091d5abd7 Add todo comment 2025-06-24 14:41:50 -03:00
Jussi Saurio
fcc070c27e Remove unused method 2025-06-24 14:41:50 -03:00
Jussi Saurio
8d4ed110c0 alloc page1 on first tx (read OR write) - otherwise e.g. select * from sqlite_schema panics 2025-06-24 14:41:50 -03:00
Jussi Saurio
d05030ed64 fix autovacuum test 2025-06-24 14:41:50 -03:00
Diego Reis
af193ef76a Move first page allocation logic to begin_write_tx 2025-06-24 14:41:50 -03:00
Jussi Saurio
acafe71d9e Dont allocate fresh page1 if it's in the WAL 2025-06-24 14:41:50 -03:00
Diego Reis
f0f9ad4844 core: Get rid of maybe_init_database_file
Initialization now only occurs in the first write transaction
2025-06-24 14:41:50 -03:00
Diego Reis
75fdbd73c6 core: Add count of pages in Pager and fix page1 initialization 2025-06-24 14:41:49 -03:00
Jussi Saurio
cc2e14b11c Read page 1 from pager always, no separate db_header 2025-06-24 14:41:49 -03:00
Nils Koch
2827b86917 chore: fix clippy warnings 2025-06-23 19:52:13 +01:00
PThorpe92
33b52bfb84 Replace refcel in wal sync, add counter timeout to conn close shutdown 2025-06-13 11:12:42 +03:00
PThorpe92
9f966910bc Add manual wal sync before checkpoint in connection Drop 2025-06-13 11:11:30 +03:00
Jussi Saurio
ace1e02fc0 Remove leftover info trace 2025-06-10 16:51:34 +03:00
Jussi Saurio
a5aeff9a3d Fix index insert accidentally double-inserting after balance 2025-06-10 14:16:26 +03:00
Zaid Humayun
e994adfb40 Persisting database header and pointer map page to cache
This commit ensures that the metadata in the database header and the pointer map pages allocated are correctly persisted to the page cache. This was not being done earlier.
2025-06-06 23:14:25 +05:30
Zaid Humayun
e7d09edf09 fix clippy warnings 2025-06-06 23:14:25 +05:30
Zaid Humayun
1f5025541c addresses comment https://github.com/tursodatabase/limbo/pull/1600#discussion_r2115796655 by @jussisaurio
this commit ensures that ptrmap operations return a CursorResult so operation can be suspended & later retried
2025-06-06 23:14:25 +05:30
Zaid Humayun
8efbce5980 Fixes tests after asserting MIN_PAGE_SIZE
this commit fixes tests that broke after addding the MIN_PAGE_SIZE assertion
2025-06-06 23:14:25 +05:30
Zaid Humayun
6e87761a34 Addresses comment https://github.com/tursodatabase/limbo/pull/1600#discussion_r2115842804 by @jussisaurio
this commit adds an assert into ptrmap_page_cycle_length
2025-06-06 23:14:25 +05:30
Zaid Humayun
20e20b8a32 Larger compiler directive. Addresses https://github.com/tursodatabase/limbo/pull/1600#discussion_r2115820195
this commit places all pointer map functionality within a module called ptrmap guarded by a compiler directive
2025-06-06 23:14:25 +05:30
Zaid Humayun
33fc60232c removed unnecessary comment 2025-06-06 23:14:25 +05:30
Zaid Humayun
8e6fb1d28f addresses comments by @jussisaurio 2025-06-06 23:14:25 +05:30
Zaid Humayun
0b5338ec7e fixed off by one error 2025-06-06 23:14:25 +05:30