FastDB簡(jiǎn)單介紹(Linux)

(本文內(nèi)容主要是通過(guò)學(xué)習(xí)官網(wǎng)、博客及閱讀官網(wǎng)demo做出的總結(jié))

FastDB是一個(gè)內(nèi)存數(shù)據(jù)庫(kù),通過(guò)把數(shù)據(jù)加載到內(nèi)存中實(shí)現(xiàn)對(duì)數(shù)據(jù)的操作,相比于傳統(tǒng)的數(shù)據(jù)庫(kù),操作的速度更快,但是存在一個(gè)缺點(diǎn)就是使用FastDB數(shù)據(jù)庫(kù)的應(yīng)用程序都必須運(yùn)行在同一臺(tái)主機(jī)上。

1 簡(jiǎn)單介紹
2 訪問(wèn)類型
3 使用流程
4 遇到的問(wèn)題及解決辦法
5 代碼實(shí)例
6 總結(jié)

一、 簡(jiǎn)單介紹

1 將數(shù)據(jù)完全加載到內(nèi)存,在內(nèi)存中實(shí)現(xiàn)對(duì)數(shù)據(jù)的管理;

2 只讀模式線程、單個(gè)更改模式線程和多個(gè)只讀模式線程間并發(fā)執(zhí)行;

3 最小單位塊:分配量子(16字節(jié));

4 事物提交協(xié)議基于一個(gè)影子根頁(yè)算法,對(duì)數(shù)據(jù)庫(kù)執(zhí)行原子更新操作,恢復(fù)效率高;

影子根頁(yè)算法:數(shù)據(jù)庫(kù)中每條對(duì)象都具有唯一標(biāo)識(shí)符用作一個(gè)數(shù)組(對(duì)象索引)的下標(biāo),元素值表示對(duì)象的一個(gè)句柄。(FastDB中存在兩個(gè)索引:當(dāng)前索引和影子索引)

5 內(nèi)存數(shù)據(jù)結(jié)構(gòu)組織:HASH、T樹(shù)。

HASH:具有最高查找效率(不適用于插入操作中,鍵值沖突發(fā)生頻率較高的場(chǎng)景);
T樹(shù):僅次于HASH(不適用于有頻繁的添加、刪除動(dòng)作的場(chǎng)景);

在FastDB中,聲明為HASH的KEY,采用HASH結(jié)構(gòu),聲明為INDEXED的KEY采用T樹(shù)結(jié)構(gòu)。

二、 訪問(wèn)類型

1 一共四種訪問(wèn)類型:dbDatabase::dbReadOnly、dbDatabase::dbAllAccess、dbDatabase::dbConcurrentRead、dbDatabase::dbConcurrentUpdate;

2 FastDB不支持客戶端/服務(wù)器結(jié)構(gòu)(內(nèi)存數(shù)據(jù)庫(kù),不能跨服務(wù)器);

3 dbDatabase::dbReadOnly:默認(rèn)是這種模式;

4 dbDatabase::dbAllAccess:如果該進(jìn)程使用了insert、update、delete等修改數(shù)據(jù)庫(kù)的操作,其他訪問(wèn)該庫(kù)的進(jìn)程的所有操作(包括open、select)都會(huì)被阻塞,直到該操作提交或回滾。(該模式我自己在寫(xiě)代碼時(shí)還沒(méi)有用到過(guò));

5 dbDatabase::dbConcurrentUpdate:如果某進(jìn)程對(duì)數(shù)據(jù)進(jìn)行修改性操作,同時(shí)另外的進(jìn)程使用 dbDatabase::dbReadOnly 或者 dbDatabase::dbConcurrentRead 讀數(shù)據(jù),不會(huì)出現(xiàn)阻塞情況。
但是 dbDatabase::dbReadOnly 會(huì)把未提交的臟數(shù)據(jù)讀出來(lái),而dbDatabase::dbConcurrentRead不會(huì);

6 多個(gè)進(jìn)程使用 dbDatabase::dbConcurrentUpdate 實(shí)際效果和 dbDatabase::dbAllAccess 一樣(阻塞);

7 不要把 dbDatabase::dbConcurrentUpdate 和 dbDatabase::dbConcurrentRead 模式混用,不能同時(shí)啟動(dòng)兩個(gè)線程,其中一個(gè)用 dbConcurrentUpdate 模式打開(kāi)數(shù)據(jù)庫(kù),另一個(gè)用 dbConcurrentRead 模式;

8 在 dbDatabase::dbConcurrentUpdate 模式下不要使用 dbDatabase::precommit方法。

三、 使用流程(Linux)

1 在fastdb官網(wǎng)下載安裝包進(jìn)行安裝;

2 在服務(wù)器上安裝fastdb,可以參考這個(gè)博主的文章(fastdb安裝配置);

3 編寫(xiě)測(cè)試文件,或者直接在下載的fastdb安裝包中找一個(gè)example文件進(jìn)行測(cè)試;

4 編寫(xiě)Makefile文件,注意添加以下內(nèi)容:-I/usr/local/include/fastdb -L/usr/local/lib -lrt -lz -lfastdb (上面的內(nèi)容根據(jù)自己的實(shí)際安裝路徑進(jìn)行調(diào)整)。

5 編譯代通過(guò),運(yùn)行代碼。

四、 遇到的問(wèn)題及解決辦法

1 undefined reference to dbDatabase::~ 等報(bào)錯(cuò)

原因 :沒(méi)有成功引入相關(guān)的頭文件或者.so文件;

解決辦法:編寫(xiě)Makefile文件時(shí)沒(méi)有添加相關(guān)的依賴(參考上面的第4點(diǎn)內(nèi)容);

2 Incompatibility between headers and library:6 vs. 4

原因:fastdb會(huì)假設(shè)絕大多數(shù)Linux是64-bit的,如果測(cè)試的是32-bit的,就會(huì)報(bào)錯(cuò);

解決辦法:根據(jù)安裝目錄,找到fastdb目錄下的config.h頭文件,將以下代碼注釋即可。(運(yùn)行的環(huán)境是64-bit的,依舊報(bào)錯(cuò),感覺(jué)不是這個(gè)原因,但是按照這種方法可以解決,很迷~)

//#if!defined(_WIN32)||defined(_WIN64)//most unixes are now 64-bit,while 32-bit windows is still quite popular
//#define LARGE_DATABASE_SUPPORT
//#endif

3 當(dāng)運(yùn)行的數(shù)據(jù)大概達(dá)到一千萬(wàn)條以上的時(shí)候,即生成的文件內(nèi)容達(dá)到2G之后,程序就會(huì)拋出異常,自動(dòng)停止,這個(gè)問(wèn)題找了很久一直也沒(méi)有解決。

五、 代碼實(shí)例

下面的代碼只是一個(gè)簡(jiǎn)單的實(shí)例,包含了表關(guān)聯(lián)(刪除一個(gè)表的數(shù)據(jù),另一個(gè)表相關(guān)的記錄也會(huì)被刪除),數(shù)組的使用,插入數(shù)據(jù)、查詢數(shù)據(jù)、刪除數(shù)據(jù)。

(ps:下面的代碼是手撕的(不是copy的服務(wù)器上面的代碼),沒(méi)有實(shí)際測(cè)過(guò),可能會(huì)有一些小小的問(wèn)題,歡迎指出,不過(guò)大體上是沒(méi)有什么問(wèn)題的。)

#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64

#include "fastdb.h"
#include "database.h"
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <sring>

using namespace std;
USE_FASTDB_NAMESPACE

dbDatabase db;

#define random(a,b) (rand()%(b-a))+a+1  //生成隨機(jī)數(shù)
#define TeacherNum 5   //老師個(gè)數(shù)
#define StudentNum 20  //學(xué)生個(gè)數(shù)

class Student;
class Teacher
{
public:
    const char* teacher_name;
    dbArray<dbReference<Student>> std_code;
    TYPE_DESCRIPTOR((KEY(teacher_name,INDEXED),OWNER(std_code,tech_code)));
};

class Student
{
public:
    const char* std_name;
    dbArray<int4> scores;  //Chinese English Math
    dbReference<Teacher> tech_code;
    TYPE_DESCRIPTOR((KEY(std_name,INDEXED),
                     FIELD(scores),
                     RELATION(tech_code,std_code)));

};

REGISTER(Teacher);  //注冊(cè)Teacher表
REGISTER(Student);  //注冊(cè)Student表

//生成老師的編號(hào)
void getRandomCharTeach(char * randnum)
{
    int num = random(0,10);  
    snprintf(randnum,sizeof(randnum),"%d",num);  //int類型轉(zhuǎn)換為char *
}

//生成學(xué)生的編號(hào)
void getRandomCharStu(char * randnum)
{
    int num = random(20,50);
    snprintf(randnum,sizeof(randnum),"%d",num);  //int類型轉(zhuǎn)換為char *
}

//生成0-100之間的隨機(jī)數(shù)
int4 getRandomIntSocre()
{
    int num = random(0,100);
    return num;
}

//查詢老師編號(hào)
void selectTeachName()
{
    cout<<"***** selectTeachName *****"<<endl;
    dbCursor<Teacher> cursorTeach;  //只讀游標(biāo)
    int n = cursorTeach.select();  //查詢
    cout<<"Teacher的數(shù)量為:"<<n<<endl;

    if(0<n)
    {
        do
        {
            cout<<"teacher_name = "<<cursorTeach->teacher_name<<" ."<<endl;
        }while(cursorTeach.next());  //游標(biāo)向后滾
    }
}

//查詢學(xué)生信息
void selectStuInfo()
{
    cout<<"***** selectStuInfo *****"<<endl;
    dbCursor<Student> cursorStu;  //只讀游標(biāo)
    int n = cursorStu.select();  //查詢
    cout<<"Student的數(shù)量為:"<<n<<endl;

    if(0<n)
    {
        do
        {
            cout<<"std_name = "<<cursorStu->std_name<<" , "<<
            "Chinese = "<<cursorStu->scores[0]<<" , "<<
            "English = "<<cursorStu->scores[1]<<" , "<<
            "Math = "<<cursorStu->scores[2]<<" ."<<endl;
        }while(cursorStu.next());  //游標(biāo)向后滾
    }
}

//刪除所有數(shù)據(jù)
void removeAllRecord()
{
    cout<<"***** removeAllRecord *****"<<endl;
    dbCursor<Teacher> cursorTeach(dbCursorForUpdate);  //寫(xiě)游標(biāo)對(duì)象
    cursorTeach.removeAll();
    dbCursor<Student> cursorStu(dbCursorForUpdate);  //寫(xiě)游標(biāo)對(duì)象
    cursorStu.removeAll();
}


int main()
{
    Teacher techer;
    Student student;

    if(db.open(_T("test")))
    {
        cout<<"Start inserting data..."<<endl;
        for(int i = 0; i < TeacherNum; i++)
        {
            char tech_num[2];
            getRandomCharTeach(tech_num);
            techer.teacher_name = tech_num;
            dbReference<Teacher> techer_class = insert(techer);
            cout<<"Insert "<<techer.teacher_name<<" to Teacher."<<endl;
            db.commit();

            //插入多個(gè)學(xué)生信息對(duì)應(yīng)當(dāng)前老師
            for(int j = 0; j < StudentNum; j++)
            {
                char std_num[2];
                getRandomCharStu(std_num);
                student.std_name = std_num;
                int Chinese = getRandomIntSocre();  //語(yǔ)文成績(jī)
                int English = getRandomIntSocre();  //英語(yǔ)成績(jī)
                int Math = getRandomIntSocre();  //數(shù)學(xué)成績(jī)
                
                student.scores(3);  //數(shù)組大小為3
                student.scores.putat(0,Chinese);  //把各科成績(jī)放到數(shù)組中
                student.scores.putat(1,English);
                student.scores.putat(2,Math);
                student.tech_code = techer_class;  //把當(dāng)前學(xué)生的信息與對(duì)應(yīng)老師相關(guān)聯(lián)
                insert(student);  
                cout<<"Insert std_name : "<<student.std_name<<" , "<<
                "Chinese : "<<Chinese<<" , "<<
                "English : "<<English<<" , "<<
                "Math : "<<Math<<" ."<<endl;
            }
            db.commit();
        }
        //查詢、刪除的實(shí)例可以在open表之后直接調(diào)就可以了,這里就不寫(xiě)了
    }
    db.commit();
    return 0;
}

六、 總結(jié)

fastDB確地有它的優(yōu)點(diǎn),但是現(xiàn)有的相關(guān)資料比較少,所以使用起來(lái)會(huì)有難度,重點(diǎn)是文件超過(guò)2G的拋異常的問(wèn)題沒(méi)有找到相關(guān)的解決方案,如果有朋友有相關(guān)解決方案,可以一起交流學(xué)習(xí)。

----------如有侵權(quán),聯(lián)系刪除!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,679評(píng)論 18 399
  • 最近在準(zhǔn)備找工作,所以自己總結(jié)了一下面試題,有些來(lái)自于網(wǎng)上的,自己做了下整理。1、JDK 和 JRE 有什么區(qū)別?...
    走路帶著風(fēng)s閱讀 309評(píng)論 0 1
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,257評(píng)論 0 62
  • 對(duì)于 iOS 框架的一些簡(jiǎn)單介紹 (顏色表示常用程度) Cocoa Touch GameKit 實(shí)現(xiàn)對(duì)游戲中心的支...
    飛奔的羊閱讀 990評(píng)論 0 3
  • 一、MySQL架構(gòu)與歷史 A.并發(fā)控制 1.共享鎖(shared lock,讀鎖):共享的,相互不阻塞的。 2.排...
    阿休閱讀 4,825評(píng)論 0 37

友情鏈接更多精彩內(nèi)容