序文
前回の記事でのLMDBの紹介に基づいて、この記事では、環境の作成、データストレージの書き込み、データの読み取りの取得など、LMDBデータベースの基本的な使用法を紹介します。
ソースコード
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は、それぞれ環境を開き、トランザクションを開き、データベースインスタンスを開くために使用されます。その中で、mdb_dbi_openは、異なるデータベース名(param 2)を介して複数のインスタンスをサポートします。
- mdb_putは、関連データを格納するために使用されます。キーと値のペア。どちらもMDB_val構造体です。
- 後続のmdb_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を介してさまざまなデータベースインスタンスを区別し、1つのデータファイルに複数のデータベースインスタンスを格納することをサポートします。
- LMDBは軽量のオープンソースデータベースライブラリであり、ハードウェアが制限された組み込み環境で一般的に使用されており、SQLステートメントをサポートしていません。
- LMDBは、mmapを介してファイルをプロセスの仮想アドレス空間にマップします。これにより、データベースアクセスを高速化できます。
- LMDBはB +ツリーアルゴリズムを使用してデータを格納し、カーソルを介してさまざまな場所のデータに簡単にアクセスできます。
- LMDBのデータストレージ/フェッチはC言語の一般的なvoid型を採用しており、型分析はプログラマーによって処理されるため、柔軟性が向上します。
総括する
LMDBのソースコードは12K行です。その実装について詳しく知りたい読者は、そのソースコードを参照できます。ソースコードには、参照用にmtest、mtest2〜mtest6などの複数のテストケースも用意されています。