内存映射文件原理_开源内存数据库
生活随笔
收集整理的這篇文章主要介紹了
内存映射文件原理_开源内存数据库
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
前言
在前文LMDB簡介的基礎(chǔ)上,本文介紹LMDB數(shù)據(jù)庫的基本用法,包括環(huán)境environment創(chuàng)建、數(shù)據(jù)存儲put、數(shù)據(jù)讀取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 存數(shù)據(jù) */
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一個事務(wù)---進(jìn)行讀 */
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創(chuàng)建env,后續(xù)mdb_env_set_maxreaders、mdb_env_set_mapsize設(shè)置環(huán)境相關(guān)參數(shù);
- Lib_CreateDir用于創(chuàng)建數(shù)據(jù)庫的目錄,官方文檔有提及:mdb_env_open參數(shù)2并不會為用戶創(chuàng)建相關(guān)目錄,因而需要提前創(chuàng)建;
- mdb_env_open、mdb_txn_begin、mdb_dbi_open分別用于打開environment、打開一個事務(wù)、打開一個數(shù)據(jù)庫instance。其中mdb_dbi_open通過不同的數(shù)據(jù)庫名(param 2)支持多實例;
- mdb_put用于存入相關(guān)數(shù)據(jù):key/value對,key/value都是MDB_val結(jié)構(gòu);
- 后續(xù)mdb_get用戶獲取數(shù)據(jù),key與put時的key相同,get成功后,我們通過強(qiáng)制類型轉(zhuǎn)換取得數(shù)據(jù)庫內(nèi)的值并打印;
- E是筆者封裝的一個宏定義,用于檢查API的返回結(jié)果,如下:
#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()))
測試結(jié)果
最后,我們將程序編譯/得到,得到如下結(jié)果。
在相關(guān)目錄產(chǎn)生數(shù)據(jù)文件和鎖文件。
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 #
結(jié)果表明:測試正確。
擴(kuò)展說明
- LMDB通過DBI區(qū)分不同的數(shù)據(jù)庫實例,支持在一個數(shù)據(jù)文件中存儲多個數(shù)據(jù)庫實例;
- LMDB是一個輕量級的開源數(shù)據(jù)庫library,常用在硬件受限的嵌入式環(huán)境,不支持SQL語句;
- LMDB通過mmap將文件映射到進(jìn)程的虛擬地址空間,可加速數(shù)據(jù)庫的訪問;
- LMDB采用B+樹算法存儲數(shù)據(jù),通過游標(biāo)cursor可方便的訪問不同位置的數(shù)據(jù);
- LMDB的數(shù)據(jù)存/取都采用c語言中通用的void類型,其類型解析由程序員自行處理,提供更大的靈活性;
總結(jié)
LMDB全部源碼12K行,想要進(jìn)一步了解其實現(xiàn)的讀者可以參閱其源碼。源碼中也提供mtest、mtest2~mtest6等多個測試案例供參閱。
總結(jié)
以上是生活随笔為你收集整理的内存映射文件原理_开源内存数据库的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一加7充电_刘作虎:一加7没有无线充电,
- 下一篇: 伏安特性曲线实验报告_电化学扩散层,Co