dwww Home | Manual pages | Find package

starting(3)                 Library Functions Manual                starting(3)

NAME
       starting - Getting Started LMDB is compact, fast, powerful, and robust
       and implements a simplified variant of the BerkeleyDB (BDB) API. (BDB is
       also very powerful, and verbosely documented in its own right.) After
       reading this page, the main LMDB API documentation should make sense.
       Thanks to Bert Hubert for creating the initial version of this writeup.

       Everything starts with an environment, created by mdb_env_create(). Once
       created, this environment must also be opened with mdb_env_open().

       mdb_env_open() gets passed a name which is interpreted as a directory
       path. Note that this directory must exist already, it is not created for
       you. Within that directory, a lock file and a storage file will be
       generated. If you don't want to use a directory, you can pass the
       MDB_NOSUBDIR option, in which case the path you provided is used
       directly as the data file, and another file with a '-lock' suffix added
       will be used for the lock file.

       Once the environment is open, a transaction can be created within it
       using mdb_txn_begin(). Transactions may be read-write or read-only, and
       read-write transactions may be nested. A transaction must only be used
       by one thread at a time. Transactions are always required, even for
       read-only access. The transaction provides a consistent view of the
       data.

       Once a transaction has been created, a database can be opened within it
       using mdb_dbi_open(). If only one database will ever be used in the
       environment, a NULL can be passed as the database name. For named
       databases, the MDB_CREATE flag must be used to create the database if it
       doesn't already exist. Also, mdb_env_set_maxdbs() must be called after
       mdb_env_create() and before mdb_env_open() to set the maximum number of
       named databases you want to support.

       Note: a single transaction can open multiple databases. Generally
       databases should only be opened once, by the first transaction in the
       process. After the first transaction completes, the database handles can
       freely be used by all subsequent transactions.

       Within a transaction, mdb_get() and mdb_put() can store single key/value
       pairs if that is all you need to do (but see Cursors below if you want
       to do more).

       A key/value pair is expressed as two MDB_val structures. This struct has
       two fields, mv_size and mv_data. The data is a void pointer to an array
       of mv_size bytes.

       Because LMDB is very efficient (and usually zero-copy), the data
       returned in an MDB_val structure may be memory-mapped straight from
       disk. In other words look but do not touch (or free() for that matter).
       Once a transaction is closed, the values can no longer be used, so make
       a copy if you need to keep them after that.

Cursors
       To do more powerful things, we must use a cursor.

       Within the transaction, a cursor can be created with mdb_cursor_open().
       With this cursor we can store/retrieve/delete (multiple) values using
       mdb_cursor_get(), mdb_cursor_put(), and mdb_cursor_del().

       mdb_cursor_get() positions itself depending on the cursor operation
       requested, and for some operations, on the supplied key. For example, to
       list all key/value pairs in a database, use operation MDB_FIRST for the
       first call to mdb_cursor_get(), and MDB_NEXT on subsequent calls, until
       the end is hit.

       To retrieve all keys starting from a specified key value, use MDB_SET.
       For more cursor operations, see the LMDB API docs.

       When using mdb_cursor_put(), either the function will position the
       cursor for you based on the key, or you can use operation MDB_CURRENT to
       use the current position of the cursor. Note that key must then match
       the current position's key.

   Summarizing the Opening
       So we have a cursor in a transaction which opened a database in an
       environment which is opened from a filesystem after it was separately
       created.

       Or, we create an environment, open it from a filesystem, create a
       transaction within it, open a database within that transaction, and
       create a cursor within all of the above.

       Got it?

Threads and Processes
       LMDB uses POSIX locks on files, and these locks have issues if one
       process opens a file multiple times. Because of this, do not
       mdb_env_open() a file multiple times from a single process. Instead,
       share the LMDB environment that has opened the file across all threads.
       Otherwise, if a single process opens the same environment multiple
       times, closing it once will remove all the locks held on it, and the
       other instances will be vulnerable to corruption from other processes.

       Also note that a transaction is tied to one thread by default using
       Thread Local Storage. If you want to pass read-only transactions across
       threads, you can use the MDB_NOTLS option on the environment.

Transactions, Rollbacks, etc.
       To actually get anything done, a transaction must be committed using
       mdb_txn_commit(). Alternatively, all of a transaction's operations can
       be discarded using mdb_txn_abort(). In a read-only transaction, any
       cursors will not automatically be freed. In a read-write transaction,
       all cursors will be freed and must not be used again.

       For read-only transactions, obviously there is nothing to commit to
       storage. The transaction still must eventually be aborted to close any
       database handle(s) opened in it, or committed to keep the database
       handles around for reuse in new transactions.

       In addition, as long as a transaction is open, a consistent view of the
       database is kept alive, which requires storage. A read-only transaction
       that no longer requires this consistent view should be terminated
       (committed or aborted) when the view is no longer needed (but see below
       for an optimization).

       There can be multiple simultaneously active read-only transactions but
       only one that can write. Once a single read-write transaction is opened,
       all further attempts to begin one will block until the first one is
       committed or aborted. This has no effect on read-only transactions,
       however, and they may continue to be opened at any time.

Duplicate Keys
       mdb_get() and mdb_put() respectively have no and only some support for
       multiple key/value pairs with identical keys. If there are multiple
       values for a key, mdb_get() will only return the first value.

       When multiple values for one key are required, pass the MDB_DUPSORT flag
       to mdb_dbi_open(). In an MDB_DUPSORT database, by default mdb_put() will
       not replace the value for a key if the key existed already. Instead it
       will add the new value to the key. In addition, mdb_del() will pay
       attention to the value field too, allowing for specific values of a key
       to be deleted.

       Finally, additional cursor operations become available for traversing
       through and retrieving duplicate values.

Some Optimization
       If you frequently begin and abort read-only transactions, as an
       optimization, it is possible to only reset and renew a transaction.

       mdb_txn_reset() releases any old copies of data kept around for a read-
       only transaction. To reuse this reset transaction, call mdb_txn_renew()
       on it. Any cursors in this transaction must also be renewed using
       mdb_cursor_renew().

       Note that mdb_txn_reset() is similar to mdb_txn_abort() and will close
       any databases you opened within the transaction.

       To permanently free a transaction, reset or not, use mdb_txn_abort().

Cleaning Up
       For read-only transactions, any cursors created within it must be closed
       using mdb_cursor_close().

       It is very rarely necessary to close a database handle, and in general
       they should just be left open.

The Full API
       The full LMDB API documentation lists further details, like how to:

       • size a database (the default limits are intentionally small)
       • drop and clean a database
       • detect and report errors
       • optimize (bulk) loading speed
       • (temporarily) reduce robustness to gain even more speed
       • gather statistics about the database
       • define custom sort orders
LMDB                            Wed Aug 16 2023                     starting(3)

Generated by dwww version 1.16 on Sat Oct 3 06:01:11 CEST 2026.