Rust嵌入式数据库引擎mdbx-sys的使用,MDBX高性能键值存储库的Rust绑定

mdbx-sys = “13.6.0”

// 示例代码:使用mdbx-sys进行基本的数据库操作
use mdbx_sys as ffi;
use std::ptr;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建环境
    let mut env: *mut ffi::MDBX_env = ptr::null_mut();
    unsafe {
        // 初始化环境
        let result = ffi::mdbx_env_create(&mut env);
        if result != ffi::MDBX_SUCCESS {
            return Err("Failed to create environment".into());
        }

        // 设置环境路径
        let path = "./mdbx_example\0".as_ptr() as *const i8;
        let result = ffi::mdbx_env_set_path(env, path);
        if result != ffi::MDBX_SUCCESS {
            return Err("Failed to set environment path".into());
        }

        // 打开环境
        let result = ffi::mdbx_env_open(env, ffi::mdbx_env_flags_t::MDBX_NOSUBDIR, 0o644);
        if result != ffi::MDBX_SUCCESS {
            return Err("Failed to open environment".into());
        }

        // 开始事务
        let mut txn: *mut ffi::MDBX_txn = ptr::null_mut();
        let result = ffi::mdbx_txn_begin(env, ptr::null_mut(), ffi::mdbx_txn_flags_t::MDBX_TXN_READWRITE, &mut txn);
        if result != ffi::MDBX_SUCCESS {
            return Err("Failed to begin transaction".into());
        }

        // 打开数据库
        let mut dbi: ffi::MDBX_dbi = 0;
        let result = ffi::mdbx_dbi_open(txn, ptr::null(), ffi::mdbx_db_flags_t::MDBX_CREATE, &mut dbi);
        if result != ffi::MDBX_SUCCESS {
            return Err("Failed to open database".into());
        }

        // 准备键值对
        let key = "test_key\0".as_bytes();
        let value = "test_value\0".as_bytes();
        
        let mut key_val = ffi::MDBX_val {
            iov_base: key.as_ptr() as *mut _,
            iov_len: key.len(),
        };
        
        let mut data_val = ffi::MDBX_val {
            iov_base: value.as_ptr() as *mut _,
            iov_len: value.len(),
        };

        // 插入数据
        let result = ffi::mdbx_put(txn, dbi, &mut key_val, &mut data_val, ffi::mdbx_put_flags_t::MDBX_UPSERT);
        if result != ffi::MDBX_SUCCESS {
            return Err("Failed to put data".into());
        }

        // 提交事务
        let result = ffi::mdbx_txn_commit(txn);
        if result != ffi::MDBX_SUCCESS {
            return Err("Failed to commit transaction".into());
        }

        // 清理环境
        ffi::mdbx_env_close(env);
    }

    println!("Operation completed successfully!");
    Ok(())
}

1 回复

mdbx-sys:Rust嵌入式数据库引擎绑定

介绍

mdbx-sys是MDBX(一个高性能嵌入式键值存储库)的Rust语言绑定。MDBX基于LMDB开发,提供了更好的性能和可靠性,特别适合嵌入式系统和需要高性能数据存储的场景。

主要特性

  • 内存映射存储架构
  • ACID事务支持
  • 多版本并发控制(MVCC)
  • 零拷贝数据访问
  • 跨平台支持

使用方法

添加依赖

在Cargo.toml中添加:

[dependencies]
mdbx-sys = "0.9"

基本示例

use mdbx_sys as ffi;
use std::ptr;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建环境
    let mut env: *mut ffi::MDBX_env = ptr::null_mut();
    unsafe {
        let result = ffi::mdbx_env_create(&mut env);
        if result != 0 {
            return Err("创建环境失败".into());
        }
        
        // 设置映射大小
        ffi::mdbx_env_set_mapsize(env, 1024 * 1024 * 100); // 100MB
        
        // 打开环境
        let result = ffi::mdbx_env_open(env, "./data", 0, 0o600);
        if result != 0 {
            return Err("打开环境失败".into());
        }
        
        // 开始事务
        let mut txn: *mut ffi::MDBX_txn = ptr::null_mut();
        let result = ffi::mdbx_txn_begin(env, ptr::null_mut(), 0, &mut txn);
        if result != 0 {
            return Err("开始事务失败".into());
        }
        
        // 打开数据库
        let mut dbi: ffi::MDBX_dbi = 0;
        let result = ffi::mdbx_dbi_open(txn, ptr::null(), 0, &mut dbi);
        if result != 0 {
            return Err("打开数据库失败".into());
        }
        
        // 准备键值对
        let key = "test_key";
        let value = "test_value";
        
        // 放入数据
        let mut put_key = ffi::MDBX_val {
            iov_len: key.len(),
            iov_base: key.as_ptr() as *mut _,
        };
        
        let mut put_val = ffi::MDBX_val {
            iov_len: value.len(),
            iov_base: value.as_ptr() as *mut _,
        };
        
        let result = ffi::mdbx_put(txn, dbi, &mut put_key, &mut put_val, 0);
        if result != 0 {
            return Err("插入数据失败".into());
        }
        
        // 提交事务
        ffi::mdbx_txn_commit(txn);
        
        // 清理环境
        ffi::mdbx_env_close(env);
    }
    
    Ok(())
}

数据读取示例

unsafe {
    // 开始只读事务
    let mut txn: *mut ffi::MDBX_txn = ptr::null_mut();
    ffi::mdbx_txn_begin(env, ptr::null_mut(), ffi::MDBX_TXN_RDONLY, &mut txn);
    
    let mut key = ffi::MDBX_val {
        iov_len: key.len(),
        iov_base: key.as_ptr() as *mut _,
    };
    
    let mut data: ffi::MDBX_val = std::mem::zeroed();
    
    // 获取数据
    let result = ffi::mdbx_get(txn, dbi, &mut key, &mut data);
    if result == 0 {
        let value = std::slice::from_raw_parts(
            data.iov_base as *const u8,
            data.iov_len
        );
        println!("获取的值: {:?}", std::str::from_utf8(value).unwrap());
    }
    
    ffi::mdbx_txn_abort(txn);
}

完整示例demo

use mdbx_sys as ffi;
use std::ptr;
use std::ffi::CString;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建环境
    let mut env: *mut ffi::MDBX_env = ptr::null_mut();
    unsafe {
        // 初始化环境
        let result = ffi::mdbx_env_create(&mut env);
        if result != 0 {
            return Err("创建环境失败".into());
        }
        
        // 设置内存映射大小为100MB
        ffi::mdbx_env_set_mapsize(env, 1024 * 1024 * 100);
        
        // 创建数据目录
        std::fs::create_dir_all("./data")?;
        
        // 打开环境
        let path = CString::new("./data").unwrap();
        let result = ffi::mdbx_env_open(env, path.as_ptr(), 0, 0o600);
        if result != 0 {
            return Err("打开环境失败".into());
        }
        
        // 开始写事务
        let mut txn: *mut ffi::MDBX_txn = ptr::null_mut();
        let result = ffi::mdbx_txn_begin(env, ptr::null_mut(), 0, &mut txn);
        if result != 0 {
            return Err("开始事务失败".into());
        }
        
        // 打开数据库
        let mut dbi: ffi::MDBX_dbi = 0;
        let result = ffi::mdbx_dbi_open(txn, ptr::null(), 0, &mut dbi);
        if result != 0 {
            return Err("打开数据库失败".into());
        }
        
        // 准备测试数据
        let keys = ["key1", "key2", "key3"];
        let values = ["value1", "value2", "value3"];
        
        // 批量插入数据
        for i in 0..keys.len() {
            let key = keys[i];
            let value = values[i];
            
            let mut put_key = ffi::MDBX_val {
                iov_len: key.len(),
                iov_base: key.as_ptr() as *mut _,
            };
            
            let mut put_val = ffi::MDBX_val {
                iov_len: value.len(),
                iov_base: value.as_ptr() as *mut _,
            };
            
            let result = ffi::mdbx_put(txn, dbi, &mut put_key, &mut put_val, 0);
            if result != 0 {
                ffi::mdbx_txn_abort(txn);
                return Err("插入数据失败".into());
            }
        }
        
        // 提交写事务
        ffi::mdbx_txn_commit(txn);
        
        // 开始只读事务用于查询
        let mut read_txn: *mut ffi::MDBX_txn = ptr::null_mut();
        let result = ffi::mdbx_txn_begin(env, ptr::null_mut(), ffi::MDBX_TXN_RDONLY, &mut read_txn);
        if result != 0 {
            return Err("开始只读事务失败".into());
        }
        
        // 查询所有数据
        println!("数据库内容:");
        for key in keys.iter() {
            let mut mdbx_key = ffi::MDBX_val {
                iov_len: key.len(),
                iov_base: key.as_ptr() as *mut _,
            };
            
            let mut data: ffi::MDBX_val = std::mem::zeroed();
            
            let result = ffi::mdbx_get(read_txn, dbi, &mut mdbx_key, &mut data);
            if result == 0 {
                let value = std::slice::from_raw_parts(
                    data.iov_base as *const u8,
                    data.iov_len
                );
                println!("{}: {}", key, std::str::from_utf8(value).unwrap());
            }
        }
        
        // 中止只读事务
        ffi::mdbx_txn_abort(read_txn);
        
        // 清理环境
        ffi::mdbx_env_close(env);
    }
    
    println!("操作完成!");
    Ok(())
}

注意事项

  1. 确保在使用前正确初始化环境
  2. 事务处理需要手动管理提交和回滚
  3. 注意内存安全,正确处理指针和生命周期
  4. 建议在生产环境中使用更高级的封装库

性能建议

  • 合理设置映射大小
  • 使用批量操作提高性能
  • 根据读写比例选择合适的事务模式
  • 定期进行数据库维护和优化
回到顶部