- Implement
std::error::ErrorforSetDurabilityError - Fix compilation error on various non-tier-1 platforms, such as wasm32-unknown
- Fix performance issue where a transaction with a large number of writes would cause
WriteTransaction::abort()and committing non-durable transactions to become slow.
- Fix correctness issue with
range(),extract_from_if(), andretain_in(). If a RangeBounds withstart>endwas passed as an argument andstartandendkeys were stored in different internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value pairs were between the two keys) then these methods would perform as if the argument had beenstart.. - Fix performance regression, from redb 2.x, where
Durability::Nonecommits could become linearly slower during a series of transactions.
- Fix correctness issue with
range(),extract_from_if(), andretain_in(). If a RangeBounds withstart>endwas passed as an argument andstartandendkeys were stored in different internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value pairs were between the two keys) then these methods would perform as if the argument had beenstart..
- Fix correctness issue with
range(),drain(), anddrain_filter(). If a RangeBounds withstart>endwas passed as an argument andstartandendkeys were stored in different internal pages in the database (i.e. a sufficient condition is that more than 4KiB of key-value pairs were between the two keys) then these methods would perform as if the argument had beenstart..
Use Database::upgrade(), in redb 2.6, to migrate to the v3 file format.
The v3 file format has been further optimized to reduce the size of the database. Databases with only
a few small keys will see the largest benefit, and the minimum size of a database file has decreased
from ~2.5MiB to ~50KiB. To achieve the smallest file size call Database::compact() before
dropping the Database.
Additionally, performance is ~15% better in bulk load benchmarks. This was achieved by implementing
a custom hash function for various in-memory HashSets and HashMaps, and by optimizing the usage
of buffers held in Arcs to reduce the number of atomic instructions executed.
Storage of variable width tuple types with arity greater than 1 is more efficient. The new format elides the length of any fixed width fields and uses varint encoding for the lengths of all variable width fields.
Note that this encoding is not compatible with the serialization of variable width tuples used in prior versions.
To load tuple data created prior to version 3.0, wrap them in the Legacy type.
For example, TableDefinition<u64, (&str, u32)> becomes TableDefinition<u64, Legacy<(&str, u32)>>.
Fixed width tuples, such as (u32, u64) are backwards compatible.
Key and Value can be derived using the redb-derive crate. Note that it does not support
schema migration. The recommended pattern to migrate schema is to create a new table, and then
perform a migration from the old table to the new table.
Multiple processes may open the same database file for reading by using the new ReadOnlyDatabase
type. On platforms which support file locks, this acquires a shared lock on the database file.
Non-durable transactions will now free pages when possible (pages allocated in a preceding non-durable transaction which are no longer referenced). This resolves an issue where a long sequence of non-durable transactions led to significant growth in the size of the database file. This change increases the RAM required for a sequence of non-durable transactions, such that RAM proportional to the net change in the database is now used. However, it will never use more than about 0.2% of the database file size.
- Add
ReadOnlyDatabase - Add
Builder::open_read_only() - Add
StorageBackend::close() - Add
Table::get_mut() - Add
chrono_v0_4feature flag which enables serialization of theNaiveDate,NaiveTime,NaiveDatetime,DateTime<FixedOffset>, andFixedOffsettypes in thechronocrate - Add
uuidfeature flag which enables serialization of theUuidtype in theuuidcrate - Change
StorageBackend::read()to accept a&mut [u8]output argument instead of returning aVec<u8> - Change
Table::insert_reserve()to takeusizeinstead ofu32as the argument type - Change
TypeName::name()to be public - Change
ReadTransactionStillInUseto contain aBox - Change
set_durability()to return aResult - Move
Database::cache_stats()andDatabase::begin_read()toReadableDatabasetrait - Rename
AccessGuardMuttoAccessGuardMutInPlace. Note that a newAccessGuardMutstruct has been added; it serves a different purpose - Remove
Durability::Paranoid - Fix a rare case where
check_integrity()returnedOk(false)even though no repair was required, when called on a database that was not shutdown cleanly and was automatically repaired when opened - Disallow access to the database from read transactions after the
Databaseas been dropped. Access will now returnDatabaseClosed
- Forward compatibility improvement which makes the file format more flexible to support a potential future optimization
- Fix a forward compatibility issue which caused a crash when opening databases created with redb 3.x. Note that opening 3.x databases with redb 2.x is not generally supported and only works in certain situations.
This file format improves savepoints.
Savepoints in the v3 format have constant, and small, overhead. Creating
and restoring them is also much faster. The v3 file format also supports
savepoints on large databases (v2 has a limit around 32TB). This release
creates v2 databases by default. Use Builder::create_with_file_format_v3()
and Database::upgrade(), respectively, to enable and migrate to v3.
The upcoming 3.0 release will only support the v3 file format.
- Add
Builder::create_with_file_format_v3() - Add
Database::upgrade()
- Add
rename_table()andrename_multimap_table() - Add
KeyandValueimplementations for the unary tuple type (i.e.(T,)) - Fix an issue which could cause a panic when concurrently performing read and write transactions,
when
debug_assertionswere enabled - Optimize
retain()andretain_in()to use less space in the database file - Improve handling of some internal errors to return
LockPoisonedinstead of panicking
- Add
Database::cache_stats() - Fix
open()andcreate()to returnInvalidDatawhen they are called on a database file that is not a valid redb database - Significantly speed up
restore_savepoint(). The time is takes now scales with the change delta since the savepoint was captured, rather than the size of the database file DatabaseStats::fragmented_bytes()is now more accurate
- Add
WriteTransaction::set_two_phase_commit() - Add
WriteTransaction::set_quick_repair()which enables a faster repair mechanism at the cost of slower transaction commits Durability::Paranoidis now deprecated. Useset_two_phase_commit(true)instead- Fix various bugs when repairing the database after an unclean shutdown. These could result in panics, leaked space in the database file, or database corruption
- Implement
TableHandleforReadOnlyTable - Fix bug in write cache, which caused pages to be evicted randomly. Pages are now evicted based on how recently they have been accessed
- Optimize
first()andlast()to be almost 2x faster - Improve in-memory cache algorithm to resolve edge cases where certain pages could become uncacheable under cache pressure
- Fix bug in read cache where the read cache could become disabled. This was likely to occur in multithreaded workloads when the read cache was smaller than the database file. This bug lead to 5-10x performance degradations for some workloads
- Significant performance optimizations to
compact() - Fix some additional cases where
compact()did not fully compact the database - Fix a panic that could occur in
commit()orabort()after an IO error.StorageError::PreviousIois now returned - Fix a potential panic that could occur when repairing the database after a crash
- Fix leak of database space that could occur when calling
restore_savepoint() - Fix leak of database space when calling
delete_multimap_table() - Fix database corruption which could occur when restoring a savepoint. This edge case is rare, and could only occur if the database was less than approximately 4TiB when the savepoint was created, and greater than 4TiB when the savepoint was restored
- Fix edge case where a transient I/O error that occurred during transaction commit, but then did
not reoccur when the
Databasewas dropped, could cause database corruption
Important: If your application has called restore_savepoint(), delete_multimap_table(),
or you suspect it may have experienced a transient I/O error during transaction commit.
It is recommended that you run check_integrity() after upgrading to this version.
This will both detect corruption and clean up any leaked space.
- Optimize page freeing to reduce the size of the database file
- Fix several cases where
check_integrity()would returnOk(false)instead ofOk(true) - Fix some cases where
compact()did not fully compact the database - Make the metadata overhead returned by
WriteTransaction::stats()more accurate - Return
StorageError::ValueTooLargewhen a key-value pair exceeds a total of 3.75GiB. Previously, a panic would occur for key-value pairs that were approximately 4GiB. - Downgrade several
info!log messages todebug! - Improve documentation
- Fix panic that occurred when calling
compact()when a read transaction was in progress - Fix
ReadTransaction::close()to returnOkwhen it succeeds - Performance optimizations
- Implement
KeyandValueforString - Allow users to implement
ReadableTableMetadata,ReadableTable, andReadableMultimapTable
2.0.0 uses a new file format that optimizes len() to be constant time. This means that it is not
backwards compatible with 1.x. To upgrade, consider using a pattern like that shown in the
upgrade_v1_to_v2 test.
check_integrity()now returns aDatabaseErrorinstead of aStorageError- Table metadata methods have moved to a new
ReadableTableMetadatatrait - Rename
RedbKeytoKey - Rename
RedbValuetoValue - Remove lifetimes from read-only tables
- Remove lifetime from
WriteTransactionandReadTransaction - Remove
drain()anddrain_filter()fromTable. Useretain,retain_in,extract_iforextract_from_ifinstead - impl
CloneforRange - Add support for
[T;N]as aValueorKeyas appropriate for the typeT - Add
len()andis_empty()toMultimapValue - Add
retain()andretain_in()toTable - Add
extract_if()andextract_from_if()toTable - Add
range()returning aRangewith the'staticlifetime to read-only tables - Add
get()returning a range with the'staticlifetime to read-only tables - Add
close()method toReadTransaction
- Fix
check_integrity()so that it returnsOk(true)when no repairs were preformed. Previously, it returnedOk(false)
- Export
TableStatstype - Export
MutInPlaceValuewhich allows custom types to supportinsert_reserve() - Add untyped table API which allows metadata, such as table stats, to be retrieved for at table without knowing its type at compile time
- Fix compilation on uncommon platforms (those other than Unix and Windows)
- Add
Builder::set_repair_callback()which can be used to set a callback function that will be invoked if the database needs repair while opening it. - Add support for custom storage backends. This is done by implementing the
StorageBackendtrait and using theBuilder::create_with_backendfunction. This allows the database to be stored in a location other than the filesystem - Implement
RedbKeyandRedbValueforchar - Implement
RedbKeyandRedbValueforbool - Implement
TableHandleforTable - Implement
MultimapTableHandleforMultimapTable - Fix panic that could occur when inserting a large number of fixed width values into a table within a single transaction
- Fix panic when calling
delete_table()on a table that is already open - Improve performance for fixed width types
- Support additional platforms
- Implement
RedbKeyforOption<T> - Implement
RedbValueforVec<T> - Implement
Debugfor tables - Add
ReadableTable::first()andlast()which retrieve the first and last key-value pairs, respectively` - Reduce lock contention for mixed read-write workloads
- Documentation improvements
- Add
Builder::create_file()which does the same thing ascreate()but takes aFileinstead of a path - Add
stats()to tables which provides informational statistics on the table's storage - Fix
WriteTransaction::stats()to correctly count the storage used by multi-map tables - Fix panics that could occur when operating on savepoints concurrently from multiple threads
on the same
WriteTransaction - Implement
SendforWriteTransaction - Change MSRV to 1.66
- Performance optimizations
- Fix panic when calling
compact()on certain databases - Fix panic when calling
compact()when an ephemeralSavepointexisted - Improve performance of
compact() - Relax lifetime requirements on arguments to
insert()
- Fix a rare panic when recovering a database file after a crash
- Minor performance improvement to write heavy workloads
- Fix serious data corruption issue when calling
drain()ordrain_filter()on aTablethat had uncommitted data
- Fix panic when re-opening databases of certain, small, sizes
- Fix panic when recovering some databases after a forceful shutdown
- Fix panic when recovering databases with multimaps that have fixed width values after a forceful shutdown
- Fix panic that could occur after an IO error when reopening a database
- Fix panic that could occur after an IO error when opening a table
- Improve error message when opening a table twice to include a more meaningful line number
- Performance improvements
redb has reached its first stable release! The file format is now gauranteed to be backward compatible, and the API is stable. I've run pretty extensive fuzz testing, but please report any bugs you encounter.
The following features are complete:
- MVCC with a single
WriteTransactionand multipleReadTransactions - Zero-copy reads
- ACID semantics, including non-durable transactions which only sacrifice Durability
- Savepoints which allow the state of the database to be captured and restored later
- Stabilize file format
- Improve performance of
restore_savepoint()
- Fix panic while repairing a database file after crash
- Fix rare panic in
restore_savepoint()
- Improve cache heuristic. This asymptotically improves performance on large databases. Benchmarks show 30% to 5x+
- Fix rare crash that could occur under certain conditions when inserting values > 2GiB
- Fix crash when growing database beyond 4TiB
- Fix panic when repairing a database containing a multimap table with fixed width values
- Performance optimizations
- File format simplifications
- Export
TransactionErrorandCommitError. These were unintentionally private - Implement
std::error::Errorfor all error enums
- Remove
Clonebound from range argument type ondrain()anddrain_filter() - File format changes to improve future extensibility
- Improve errors to be more granular.
Errorhas been split into multiple differentenums, which can all be implicitly converted back toErrorfor convenience - Rename
savepoint()toephemeral_savepoint() - Add support for persistent savepoints. These persist across database restarts and must be explicitly released
- Optimize
restore_savepoint()to be ~30x faster - Add experimental support for WASI. This requires nightly
- Implement
RedbKeyfor() - Fix some rare crash and data corruption bugs
- Enforce a limit of 3GiB on keys & values
- Fix database corruption bug that could occur if a
Durability::Nonecommit was made, followed by a durable commit and the durable commit crashed or encountered an I/O error duringcommit() - Fix panic when re-openning a database file, when the process that last had it open had crashed
- Fix several bugs where an I/O error during
commit()could cause a panic instead of returning anErr - Change
lengthargument toinsert_reserve()tou32 - Change
Table::len()to returnu64 - Change width of most fields in
DatabaseStatstou64 - Remove
Ktype parameter fromAccessGuardMut - Add
Database::compact()which compacts the database file - Performance optimizations
- Combine
Builder::set_read_cache_size()andBuilder::set_write_cache_size()into a single,Builder::set_cache_size()setting - Relax lifetime constraints on read methods on tables
- Optimizations to
Savepoint
- Add
Database::check_integrity()to explicitly run repair process (it is still always run if needed on db open) - Change
list_tables()to return aTableHandle - Change
delete_table()to take aTableHandle - Make
insert_reserve()API signature type safe - Change all iterators to return
Resultand propagate I/O errors - Replace
WriteStrategywithDurability::Paranoid - Remove
Builder::set_initial_size() - Enable db file shrinking on Windows
- Performance optimizations
- Remove
Builder::create_mmapped()andBuilder::open_mmapped(). The mmap backend has been removed because it was infeasible to prove that it was sound. This makes the redb API entirely safe, and the remainingFilebased backed is within a factor of ~2x on all workloads that I've benchmarked - Make
TableimplementSend. It is now possible to insert into multipleTables concurrently - Expose
AccessGuardMut,DrainandDrainFilterin the public API - Rename
RangeItertoRange - Rename
MultimapRangeItertoMultimapRange - Rename
MultimapValueItertoMultimapValue - Performance optimizations
- Fix a major data corruption issue that was introduced in version 0.12.0. It caused databases
greater than ~4GB to become irrecoverably corrupted due to an integer overflow in
PageNumber::address_rangethat was introduced by commitb2c44a824d1ba69f526a1a75c56ae8484bae7248 - Add
drain_filter()toTable - Make key and value type bounds more clear for tables
- Fix
open()on platforms with OS page size != 4KiB - Relax lifetime requirements on argument to
range()anddrain()
- Add
pop_first()andpop_last()toTable - Add
drain()toTable - Add support for
Option<T>as a value type - Add support for user defined key and value types. Users must implement
RedbKeyand/orRedbValue - Change
get(),insert(),remove()...etc to take arguments of typeimpl Borrow<SelfType> - Return
Error::UpgradeRequiredwhen opening a file with an outdated file format - Improve support for 32bit platforms
- Performance optimizations
- Remove
[u8]andstrtype support. Use&[u8]and&strinstead. - Change
get(),range()and several other methods to returnAccessGuard. - Rename
AccessGuard::to_value()tovalue() - Add a non-mmap based backend which is now the default. This makes
Database::create()andDatabase::open()safe, but has worse performance in some cases. The mmap backend is available viacreate_mmapped()/open_mmapped(). There is no difference in the file format, so applications can switch from one backend to the other. - Better handling of fsync failures
- Remove maximum database size argument from
create(). Databases are now unbounded in size - Reduce address space usage on Windows
- Remove
set_dynamic_growth() - Add
set_initial_size()toBuilder - Optimize cleanup of deleted pages. This resolves a performance issue where openning a Database or performing a small transaction, could be slow if the last committed transaction deleted a large number of pages
- Remove
set_page_size(). 4kB pages are always used now - Add
iter()method toTableandMultimapTable - Fix various lifetime issues with type that had a lifetime, such as
&strand(&[u8], u64)
- Add support for dynamic file growth on Windows
- Add support for tuple types as keys and values
- Remove
Builder::set_region_size - Save lifetime from
Savepoint - Fix crash when using
create()to open an existing database created withWriteStrategy::TwoPhase - Fix rare crash when writing a mix of small and very large values into the same table
- Performance optimizations
- Performance improvements for database files that are too large to fit in RAM
- Fix deadlock in concurrent calls to
savepoint()andrestore_savepoint() - Fix crash if
restore_savepoint()failed - Move
savepoint()andrestore_savepoint()methods toWriteTransaction - Implement
Iteratorfor the types returned fromrange()andremove_all()
- Add support for Windows
- Add
Database::set_write_strategywhich allows theWriteStrategyof the database to be changed after creation - Make
Database::begin_writeblock, instead of panic'ing, if there is another write already in progress - Add
Database::savepointandDatabase::restore_savepointwhich can be used to snapshot and rollback the database - Rename
DatabaseBuildertoBuilder - Performance optimizations for large databases
- Fix crash when
Database::open()was called on a database that had been created withWriteStrategy::TwoPhase - Change default region size on 32bit platforms to 4GiB
- Return
Errinstead of panic'ing when opening a database file with an incompatible file format version - Many optimizations to the file format, and progress toward stabilizing it
- Fix race between read & write transactions, which could cause reads to return corrupted data
- Better document the different
WriteStrategys - Fix panic when recovering a database that was uncleanly shutdown, which had been created with
WriteStrategy::Checksum(which is the default) - Fix panic when using
insert_reserve()in certain cases
- Optimize
MultimapTablestorage format to useO(k * log(n_k) + v * log(n_v / n_k))space instead ofO(k * log(n_k + n_v) + v * log(n_k + n_v))space, where k is the size of the stored keys, v is the size of the stored values, n_k is the number of stored keys, n_v is the number of stored values - Fix compilation errors for 32bit x86 targets
- Add support for the unit type,
(), as a value - Return an error when attempting to open the same database file for writing in multiple locations, concurrently
- More robust handling of fsync failures
- Change
MultimapTable::rangeto return an iterator of key-value-collection pairs, instead of key-value pairs - Automatically abort
WriteTransactionon drop
- Add single phase with checksum commit strategy. This is now the default and reduces commit latency by ~2x. For more details,
see the design doc and
blog post. The previous behavior is available
via
WriteStrategy::Throughput, and can have better performance when writing a large number of bytes per transaction.
- Fix a bug where re-opening a
Tableduring aWriteTransactionlead to stale results being read
- Fix a serious data corruption issue that caused many write operations to corrupt the database
- Make redb region size configurable
- Implement garbage collection of empty regions
- Fixes and optimizations to make the file format more efficient
- Add information log messages which can be enabled with the
loggingfeature - Add support for
[u8; N]type - Optimize storage of fixed width types. The value length is no longer stored, which reduces storage space by ~50% for
u64, 2x foru32, and also improves performance.
- Change
insert()to return anOption<V>with the previous value, instead of()
- Improved documentation
- Initial beta release