CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-lmdb

Universal Python binding for the LMDB 'Lightning' Database

Pending
Overview
Eval results
Files

transactions.mddocs/

Transaction Management

ACID transaction handling for consistent database operations. Transactions provide atomicity, consistency, isolation, and durability guarantees for all database modifications. LMDB supports concurrent readers with exclusive writers using MVCC (Multi-Version Concurrency Control).

Capabilities

Transaction Creation

Create read-only or read-write transactions with optional parent transaction support and buffer management.

class Environment:
    def begin(self, db=None, parent=None, write: bool = False, 
              buffers: bool = False) -> Transaction:
        """
        Begin a new transaction.

        Parameters:
        - db: Default database handle for transaction operations
        - parent: Parent transaction (for nested transactions)
        - write: Enable write operations (default read-only)
        - buffers: Return buffer objects instead of copying data

        Returns:
        Transaction instance

        Note:
        Write transactions are exclusive - only one write transaction per environment.
        Read transactions are concurrent and don't block each other or writers.
        """

Transaction Lifecycle

Commit or abort transactions with proper resource cleanup and error handling.

class Transaction:
    def commit(self) -> None:
        """
        Commit all operations in transaction and close it.
        Changes become visible to other transactions.
        
        Raises:
        Various errors if commit fails (disk full, corruption, etc.)
        """

    def abort(self) -> None:
        """
        Abandon all operations and close transaction.
        All changes are discarded without affecting database.
        Safe to call multiple times.
        """

    def id(self) -> int:
        """
        Get unique transaction identifier.

        Returns:
        Transaction ID (monotonically increasing)
        """

Data Retrieval

Read operations for accessing stored data with flexible default handling and multi-database support.

class Transaction:
    def get(self, key: bytes, default=None, db=None) -> bytes:
        """
        Retrieve value for given key.

        Parameters:
        - key: Key to lookup (bytes object)
        - default: Value returned if key not found
        - db: Database handle (uses transaction default if None)

        Returns:
        Value bytes or default if key not found
        """

Data Modification

Write operations for storing, updating, and removing data with extensive control options.

class Transaction:
    def put(self, key: bytes, value: bytes, dupdata: bool = True, 
            overwrite: bool = True, append: bool = False, db=None) -> bool:
        """
        Store key-value pair in database.

        Parameters:
        - key: Key bytes (must not be empty)
        - value: Value bytes
        - dupdata: Allow duplicate keys (ignored if database doesn't support duplicates)
        - overwrite: Replace existing value (False raises KeyExistsError if key exists)
        - append: Optimize for appending (key must be >= all existing keys)
        - db: Database handle

        Returns:
        True if key was inserted, False if key existed and was updated

        Raises:
        KeyExistsError: If overwrite=False and key exists
        MapFullError: If database is full
        """

    def replace(self, key: bytes, value: bytes, db=None) -> bytes:
        """
        Replace existing value and return old value.

        Parameters:
        - key: Key to replace
        - value: New value
        - db: Database handle

        Returns:
        Previous value

        Raises:
        NotFoundError: If key doesn't exist
        """

    def pop(self, key: bytes, db=None) -> bytes:
        """
        Get value and delete key in single operation.

        Parameters:
        - key: Key to retrieve and delete
        - db: Database handle

        Returns:
        Value that was stored

        Raises:
        NotFoundError: If key doesn't exist
        """

    def delete(self, key: bytes, value: bytes = b'', db=None) -> bool:
        """
        Delete key-value pair from database.

        Parameters:
        - key: Key to delete
        - value: Specific value to delete (for duplicate keys, empty for any value)
        - db: Database handle

        Returns:
        True if key was found and deleted

        Raises:
        NotFoundError: If key doesn't exist (when value specified)
        """

Database Operations

Transaction-scoped database management including statistics and database deletion.

class Transaction:
    def stat(self, db) -> dict:
        """
        Get database statistics within transaction context.

        Parameters:
        - db: Database handle

        Returns:
        Dictionary with statistics:
        - psize: Page size
        - depth: B-tree depth  
        - branch_pages: Internal pages
        - leaf_pages: Leaf pages
        - overflow_pages: Overflow pages
        - entries: Data items
        """

    def drop(self, db, delete: bool = True) -> None:
        """
        Empty or delete database.

        Parameters:
        - db: Database handle
        - delete: If True, delete database; if False, empty database

        Note:
        Cannot delete the default database, only empty it
        """

Cursor Creation

Create cursors for iteration and positioned access within transaction context.

class Transaction:
    def cursor(self, db=None) -> Cursor:
        """
        Create cursor for iterating over database.

        Parameters:
        - db: Database handle (uses transaction default if None)

        Returns:
        Cursor instance bound to this transaction and database
        """

Usage Examples

Basic Transaction Operations

import lmdb

env = lmdb.open('/path/to/database')

# Write transaction with context manager (recommended)
with env.begin(write=True) as txn:
    # Store data
    txn.put(b'user:1', b'{"name": "Alice", "age": 30}')
    txn.put(b'user:2', b'{"name": "Bob", "age": 25}')
    
    # Update existing data
    txn.put(b'user:1', b'{"name": "Alice Smith", "age": 31}')
    
    # Conditional insert (fails if key exists)
    try:
        txn.put(b'user:3', b'{"name": "Charlie"}', overwrite=False)
    except lmdb.KeyExistsError:
        print("User 3 already exists")
    
    # Get and delete in one operation
    old_value = txn.pop(b'user:2')
    print(f"Removed user: {old_value}")
    
    # Transaction auto-commits when leaving context successfully

# Read transaction
with env.begin() as txn:
    user1 = txn.get(b'user:1')
    if user1:
        print(f"User 1: {user1}")
    
    # Safe get with default
    user99 = txn.get(b'user:99', default=b'Not found')
    print(f"User 99: {user99}")

env.close()

Manual Transaction Management

import lmdb

env = lmdb.open('/path/to/database')

# Manual transaction management (not recommended - use context managers)
txn = env.begin(write=True)
try:
    txn.put(b'key1', b'value1')
    txn.put(b'key2', b'value2')
    
    # Simulate error condition
    if some_error_condition:
        txn.abort()  # Discard changes
        print("Transaction aborted")
    else:
        txn.commit()  # Save changes
        print("Transaction committed")
        
except Exception as e:
    txn.abort()  # Always abort on exception
    print(f"Transaction failed: {e}")

env.close()

Multi-Database Transactions

import lmdb

env = lmdb.open('/path/to/database', max_dbs=3)

# Open multiple databases
users_db = env.open_db(b'users')
posts_db = env.open_db(b'posts')
comments_db = env.open_db(b'comments')

# Atomic operations across multiple databases
with env.begin(write=True) as txn:
    # Create user
    user_id = b'user:123'
    txn.put(user_id, b'{"name": "Alice"}', db=users_db)
    
    # Create post by user
    post_id = b'post:456'
    txn.put(post_id, b'{"user_id": "123", "title": "Hello World"}', db=posts_db)
    
    # Add comment to post
    comment_id = b'comment:789'
    txn.put(comment_id, b'{"post_id": "456", "text": "Great post!"}', db=comments_db)
    
    # All operations committed atomically

# Read from multiple databases
with env.begin() as txn:
    user = txn.get(b'user:123', db=users_db)
    post = txn.get(b'post:456', db=posts_db)
    comment = txn.get(b'comment:789', db=comments_db)
    
    print(f"User: {user}")
    print(f"Post: {post}")
    print(f"Comment: {comment}")

env.close()

Error Handling

import lmdb

env = lmdb.open('/path/to/database')

try:
    with env.begin(write=True) as txn:
        txn.put(b'key1', b'value1')
        
        # This might fail if database is full
        large_value = b'x' * 1000000
        txn.put(b'large_key', large_value)
        
except lmdb.MapFullError:
    print("Database is full - increase map_size")
    
except lmdb.Error as e:
    print(f"LMDB error: {e}")
    
finally:
    env.close()

Install with Tessl CLI

npx tessl i tessl/pypi-lmdb

docs

core-operations.md

cursors.md

index.md

multi-database.md

transactions.md

tile.json