重启应用后无法从MDBX键值存储中读取字符串键
MDBX字符串键重启后无法读取的问题
- 首次运行应用可正常插入并读取字符串键对应的值,但重启应用(注释插入代码后)无法读取该字符串键的值,int类型键则能正常读取。
相关代码
#include <cstring> #include <exception> #include <iostream> #include "mdbx/mdbx.h" #include "mdbx/mdbx.h++" #include <string> using namespace mdbx; int main(int, char**) { std::cout << "Starting mdbx app!"<< std::endl ; env::geometry db_geometry; env_managed::create_parameters create_param; create_param.geometry=db_geometry; mdbx::env::operate_parameters operator_param; operator_param.max_maps=MDBX_MAX_DBI; std::string&& db_file_path="./db/my-db"; mdbx::env_managed env1 = mdbx::env_managed(db_file_path,create_param, operator_param); auto tx = env1.start_write(); MDBX_dbi dbi; mdbx_dbi_open(tx,"test1",MDBX_db_flags_t::MDBX_CREATE,&dbi); mdbx::map_handle handle(dbi); MDBX_val k; k.iov_len=sizeof(int); std::string j ="k1"; k.iov_base=&j; MDBX_val v; auto hw = "v1"; v.iov_len=std::strlen(hw); v.iov_base=(char*)hw; tx.insert(handle,k,v); std::cout << tx.get(handle,k).string_view() << std::endl; tx.commit(); env1.close(); }
重启后的报错
terminate called after throwing an instance of 'mdbx::not_found' what(): MDBX_NOTFOUND: No matching key/data pair found
问题分析与解决
错误根源
- 键长度设置错误:你把字符串键的
iov_len设为sizeof(int)(通常4字节),但"k1"的实际长度是2字节。插入时虽然能临时读取,但重启后用错误长度匹配,自然找不到对应键。 - 键的指针指向错误:
k.iov_base = &j传递的是std::string对象本身的地址,而非字符串内部的实际数据缓冲区。std::string的内存结构包含额外元数据,存储这个地址等于把对象结构而非字符串内容作为键存入了数据库。
修正代码
把字符串键的MDBX_val初始化改为正确方式:
std::string j = "k1"; MDBX_val k; k.iov_len = j.size(); // 使用字符串实际长度 k.iov_base = const_cast<char*>(j.data()); // 指向字符串的实际数据
重启后的读取代码也要用同样的方式初始化k,才能正确匹配到之前存储的键。
简化写法(推荐)
直接使用MDBX C++ API的便捷重载,避免手动操作MDBX_val:
// 插入时 tx.insert(handle, j, std::string(hw)); // 读取时 auto value = tx.get(handle, j); std::cout << value.string_view() << std::endl;
内容的提问来源于stack exchange,提问作者Anurag Vohra
相关产品推荐
相关产品推荐

