内存映射文件原理_开源内存数据库
2023-06-13 09:14:58 时间
前言
在前文LMDB简介的基础上,本文介绍LMDB数据库的基本用法,包括环境environment创建、数据存储put、数据读取get等;
源码
ULONG cvtest_Test4_Lmdb()
{
INT iRet;
MDB_txn *pstTxn = NULL;
MDB_dbi stDbi;
UINT uiKey = 1;
UINT uiData = 100;
iRet = mdb_env_create(&g_pstMdbEnv);
if (0 != iRet)
{
return ERROR_FAILED;
}
mdb_env_set_maxreaders(g_pstMdbEnv, 1);
mdb_env_set_mapsize(g_pstMdbEnv, 4096 * 4096);
if (ERROR_SUCCESS != Lib_CreateDir(CVTEST_LMDB_PATH))
{
mdb_env_close(g_pstMdbEnv);
return ERROR_FAILED;
}
iRet = mdb_env_open(g_pstMdbEnv, CVTEST_LMDB_PATH, MDB_WRITEMAP, 0);
E(iRet, "Env open failed...");
iRet += mdb_txn_begin(g_pstMdbEnv, NULL, 0, &pstTxn);
E(iRet, "Txm begin open failed...");
iRet += mdb_dbi_open(pstTxn, NULL, MDB_CREATE, &stDbi);
E(iRet, "dbi_open failed...");
MDB_val stKey;
MDB_val stData;
stKey.mv_size = sizeof(UINT);
stKey.mv_data = (VOID *)&uiKey;
/* mdb_put 存数据 */
stData.mv_size = sizeof(UINT);
stData.mv_data = (VOID *)&uiData;
iRet = mdb_put(pstTxn, stDbi, &stKey, &stData, 0);
if (iRet != MDB_SUCCESS)
{
printf("mdb_put failed : %s\n", mdb_strerror(iRet));
mdb_env_close(g_pstMdbEnv);
return ERROR_FAILED;
}
mdb_txn_commit(pstTxn);
/* 重新begin一个事务---进行读 */
MDB_txn *pstReadTxn = NULL;
MDB_dbi stDbiRead;
MDB_val stReadValue;
CHAR szBuf[BUF_LEN_100] = {0, };
stReadValue.mv_size = BUF_LEN_100;
stReadValue.mv_data = (VOID *)szBuf;
mdb_txn_begin(g_pstMdbEnv, NULL, MDB_RDONLY, &pstReadTxn);
iRet = mdb_dbi_open(pstReadTxn, NULL, 0, &stDbiRead);
iRet += mdb_get(pstReadTxn, stDbiRead, &stKey, &stReadValue);
if (iRet != MDB_SUCCESS)
{
printf("mdb_get failed : %s\n", mdb_strerror(iRet));
return ERROR_FAILED;
}
printf("stReadValue.data is %d \n", *(UINT *)stReadValue.mv_data);
return ERROR_SUCCESS;
}
源码解读
- 按照LMDB官方介绍文档,先通过mdb_env_create创建env,后续mdb_env_set_maxreaders、mdb_env_set_mapsize设置环境相关参数;
- Lib_CreateDir用于创建数据库的目录,官方文档有提及:mdb_env_open参数2并不会为用户创建相关目录,因而需要提前创建;
- mdb_env_open、mdb_txn_begin、mdb_dbi_open分别用于打开environment、打开一个事务、打开一个数据库instance。其中mdb_dbi_open通过不同的数据库名(param 2)支持多实例;
- mdb_put用于存入相关数据:key/value对,key/value都是MDB_val结构;
- 后续mdb_get用户获取数据,key与put时的key相同,get成功后,我们通过强制类型转换取得数据库内的值并打印;
- E是笔者封装的一个宏定义,用于检查API的返回结果,如下:
#define E(Rest, expr) LMDB_CHECK((Rest) == MDB_SUCCESS, #expr)
#define LMDB_CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(test)), abort()))
测试结果
最后,我们将程序编译/得到,得到如下结果。
在相关目录产生数据文件和锁文件。
zglinux cvtest # ls -lrth /home/zhaogang/code_my/lmdb/
total 32K
---------- 1 root root 192 5月 27 21:29 lock.mdb
---------- 1 root root 16M 5月 27 21:29 data.mdb
zglinux cvtest #
结果表明:测试正确。
扩展说明
- LMDB通过DBI区分不同的数据库实例,支持在一个数据文件中存储多个数据库实例;
- LMDB是一个轻量级的开源数据库library,常用在硬件受限的嵌入式环境,不支持SQL语句;
- LMDB通过mmap将文件映射到进程的虚拟地址空间,可加速数据库的访问;
- LMDB采用B+树算法存储数据,通过游标cursor可方便的访问不同位置的数据;
- LMDB的数据存/取都采用c语言中通用的void类型,其类型解析由程序员自行处理,提供更大的灵活性;
总结
LMDB全部源码12K行,想要进一步了解其实现的读者可以参阅其源码。源码中也提供mtest、mtest2~mtest6等多个测试案例供参阅。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
相关文章
- [mit6.s081] 笔记 Lab10: Mmap | 文件内存映射
- rammap使用_查看内存的命令
- 【Android 内存优化】使用 Memory Analyzer ( MAT ) 工具分析内存 ( hprof 文件转换 | MAT 工具下载 | MAT 工具使用 )
- 【Android 内存优化】图片文件压缩 ( Android 原生 API 提供的图片压缩功能能 | 图片质量压缩 | 图片尺寸压缩 )
- 【Android 内存优化】自定义组件长图组件 ( 获取图像宽高 | 计算解码区域 | 设置图像解码属性 复用 像素格式 | 图像绘制 )
- 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )
- 【Linux 内核 内存管理】内存管理系统调用 ② ( mmap 创建内存映射 | mmap 创建内存映射 与 malloc 申请内存对比 | mmap 创建内存映射 与 普通文件操作对比 )
- 内存定位问题常用命令记录
- SQLServer 错误 17067 SQL Server断言:文件: <%s>,行 = %d %s。 此错误可能与时间有关。 如果重新运行该语句后错误仍然存在,请使用 DBCC CHECKDB 来检查数据库的结构是否完整,或重新启动服务器以确保内存中的数据结构未破坏。 故障 处理 修复 支持远程
- NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件详解编程语言
- 大文件下载—之内存溢出问题解决详解编程语言
- Linux文件内存映射:实现高性能存取(linux文件内存映射)
- apLinux下实现文件内存映射:MMAP(linuxmm)
- Linux文件内存管理技术研究(linux把文件内存)
- 极致性能:Redis内存数据库的魅力(redis内存数据库)
- Redis:高效的内存数据库(redis内存数据库)
- 如何查看redis内存使用情况?(查看redis占用的内存)
- 管理SQL Server提高内存效率的实践(内存sqlserver)
- Oracle数据库内存页面大小优化研究(oracle内存页面大小)
- 深入了解Oracle内存的配置查询(oracle内存配置查询)
- 优化Oracle数据库 内存设置的窍门(oracle内存设置页面)
- Redis浩瀚存储空间,支撑大数据神迹(数据库redis内存)
- 解决Redis内存溢出的秘密武器(redis超过内存怎么办)
- 谁发明了基于内存事务的Redis(redis谁发明)
- Redis中的命令记录从文件到内存的持久化(redis记录命令的文件)
- GitHub Codespaces现已支持团队和企业云计划 配置最高32核心64GB内存
- VB读取线程、句柄及写入内存的API代码实例