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(())
}
注意事项
- 确保在使用前正确初始化环境
- 事务处理需要手动管理提交和回滚
- 注意内存安全,正确处理指针和生命周期
- 建议在生产环境中使用更高级的封装库
性能建议
- 合理设置映射大小
- 使用批量操作提高性能
- 根据读写比例选择合适的事务模式
- 定期进行数据库维护和优化