eXtremeDB數(shù)據(jù)庫簡單實用教程

1 eXtremeDB簡介

全世界第一款全內(nèi)存嵌入式實時數(shù)據(jù)庫,特別為高性能眨攘、低開銷、穩(wěn)定可靠的極速實時數(shù)據(jù)管理而設計嚣州。
內(nèi)存數(shù)據(jù)庫:將數(shù)據(jù)以程序直接使用的格式保存在主內(nèi)存之中鲫售,不僅剔除了文件I/O的開銷,也剔除了文件系統(tǒng)數(shù)據(jù)庫所需的緩沖和Cache機制该肴。其結(jié)果是相比于磁盤數(shù)據(jù)庫龟虎,其速度提高成百上千倍,以至普通PC平臺的硬件條件下就可以達到每個交易1微秒甚至更小的極限速度沙庐。
嵌入式數(shù)據(jù)庫:以鏈接庫的形式包含在應用程序之中,其開銷只有50KB~120KB佳吞,剔除了數(shù)據(jù)復制及數(shù)據(jù)翻譯的開銷拱雏,縮短了應用程序的代碼執(zhí)行路徑。 應用定制的API 應用程序?qū)XtremeDB數(shù)據(jù)庫的操作接口是根據(jù)應用數(shù)據(jù)庫設計而產(chǎn)生底扳,這些動態(tài)的API剔除了通常數(shù)據(jù)庫應用程序所必不可少的動態(tài)內(nèi)存分配铸抑,不僅提升了數(shù)據(jù)庫的實時性能,也提高了應用系統(tǒng)的可靠性衷模。

1.1 eXtremeDB特點

  • 內(nèi)存+嵌入式
  • 跨平臺的實時數(shù)據(jù)解決方案(對操作系統(tǒng)鹊汛、編譯器和處理器沒有依賴性)
  • 無動態(tài)內(nèi)存分配蒲赂,避免內(nèi)存泄漏等問題
  • 提供磁盤定時保存數(shù)據(jù)庫的功能(增量式磁盤鏡像的eXtremeLog模塊和內(nèi)存鏡像的eXtremeHA模塊)

1.2 與其他數(shù)據(jù)庫比較

數(shù)據(jù)庫服務器架構(gòu) :通過數(shù)據(jù)庫驅(qū)動程序如JDBC、ODBC等訪問數(shù)據(jù)庫服務器刁憋,數(shù)據(jù)庫服務器再操作數(shù)據(jù)庫文件(Oracle滥嘴、、MySQL和SQL Server等)至耻。允許非開發(fā)人員操作數(shù)據(jù)與程序分離若皱,便于控制需要獨立安裝部署和管理。
嵌入式數(shù)據(jù)庫: 直接將數(shù)據(jù)庫的庫文件鏈接到應用程序中尘颓。應用程序通過API訪問數(shù)據(jù)庫走触,而不是TCP/IP。只允許應用程序?qū)ζ溥M行訪問控制數(shù)據(jù)訪問控制權(quán)限完全交給應用程序不需要單獨部署服務器疤苹,與應用程序一起發(fā)布互广。

2 eXtremeDB基本概念

2.1 創(chuàng)建應用程序步驟

2.2 基本數(shù)據(jù)類型

2.3 訪問數(shù)據(jù)方法

訪問存儲在數(shù)據(jù)庫中對象的過程,主要方法有使用oid或者autoid卧土,使用散列或樹索引惫皱,按順序遍歷和使用歷史版本。

2.3.1 oid

指定了保存類時會同時保存為該類聲明的oid類型的一個oid,eXtremeDB在數(shù)據(jù)庫中為oid維護了一個特殊的索引夸溶,通過該索引便可以通過oid值定位數(shù)據(jù)庫中的對象,oid在一個數(shù)據(jù)庫模式文件中只能聲明一次逸吵。

2.3.2 autoid

與oid類似,但是autoid是在運行時期決定的值缝裁,每個autoid的值在數(shù)據(jù)庫中是唯一的扫皱。autoid通常是autoid_t類型。

2.3.3 索引

使用散列和樹索引作為數(shù)據(jù)庫中對象的唯一標識符捷绑,與oid不同韩脑,只需要保證在類中唯一即可。

2.3.4 鏈表

不關(guān)心特殊順序的遍歷粹污。

2.3.5 歷史記錄

通過histroy關(guān)鍵字維護該對象的不同版本的歷史記錄段多,每次更新該類的對象事務都會創(chuàng)建一個新版本的對象。
class Person
{
    string name;
    string address;
    uint4  salary;
    autoid_t<Person> manager;

    list;   // 鏈表遍歷
    autoid[1000];   // autoid遍歷
   tree<name> pk;   // 在name上建立樹索引
   histroy[10];    // 保存最近10個版本的對象
};

2.4 數(shù)據(jù)庫基礎操作

2.4.1 寫操作

1 創(chuàng)建一個數(shù)據(jù)庫并連接壮吩,得到數(shù)據(jù)庫句柄 mco_db_open() mco_db_connect()
2 打開一個"寫"事務进苍,得到事務句柄 mco_trans_start()
3 使用事務句柄,創(chuàng)建一個新的類對象鸭叙,獲得類句柄 類對象名_new()
4 使用類句柄觉啊,通過不同形式的"put"方式經(jīng)應用程序的值賦給對象字段 類對象名_參數(shù)名_put()
5 提交或回滾事務 mco_trans_commit()

2.4.2 讀操作

1 創(chuàng)建一個數(shù)據(jù)庫并連接,得到數(shù)據(jù)庫句柄 mco_db_open() mco_db_connect()
2 打開一個“讀”事務沈贝,得到事務句柄 mco_trans_start()
3 使用事務句柄杠人,調(diào)用某中訪問方法:oid、鏈表、散列或樹索引嗡善,若搜索成功則獲得類句柄 類對象名_oid_fin
4 通過類句柄辑莫,使用"get"方法將數(shù)據(jù)庫中存儲的值賦給程序變量 類對象名_參數(shù)名_get()
5 提交事務 mco_trans_commit()

3 Java JDBC示例

3.1 創(chuàng)建數(shù)據(jù)庫配置文件xsql.cfg

database_name : xsqldb,
database_size : 64m,
schema        : "
     #define int1      signed<1>
     #define int2      signed<2>
     #define int4      signed<4>
     #define int8      signed<8>
     #define uint8     unsigned<8>
     #define uint4     unsigned<4>
     #define uint2     unsigned<2>
     #define uint1     unsigned<1>

     declare database xsql; 

    class S
    {
        char<5>  sid;
        nullable char<20> sname; 
        nullable int4     status;
        date dat;
        char<15> city;

        list;
        autoid[1000];
        hash<sid> pk[1000];
        tree<sname> snk;
        tree<status> stk;
    };
",
sql_port : 5001

3.2 啟動數(shù)據(jù)庫

進入eXtremeDB安裝目錄下的/target/bin目錄,執(zhí)行以下指令
xsql -c xsql.cfg
-c 使用指定目錄的配置文件

3.3 應用程序中引入jar包

jar包位于eXtremeDB安裝目錄下的/target/bin目錄

3.4 程序

import java.sql.*;

/**
 * @author 蘇若墨
 */

public class SimpleJDBC
{
    /**
     * 數(shù)據(jù)庫連接
     */
    Connection con;
    /**
     * 記錄條數(shù)
     */
    static final int nRecords = 5;

    public static void main(String[] args) throws Exception
    {
        new SimpleJDBC("jdbc:extremedb:localhost");
    }

    /**
     * 操作函數(shù)罩引,完成數(shù)據(jù)庫基本操作
     * @param url
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public SimpleJDBC(String url) throws ClassNotFoundException, SQLException
    {
        String user = null;
        String password = null;

        // 1.加載驅(qū)動
        Class.forName("com.mcobject.jdbc.McoDriver");

        // 2.連接數(shù)據(jù)庫
        System.out.println("Connecting to Database URL = " + url);
        con = DriverManager.getConnection(url, user, password);

        System.out.println("Connected...");

        // 3.數(shù)據(jù)庫基本操作
        insert();

        select();

        update();

        delete();

        // 4.關(guān)閉數(shù)據(jù)庫連接
        System.out.println("Now closing the connection");
        con.close();
    }

    /**
     * 插入數(shù)據(jù)
     * @throws SQLException
     */
    void insert() throws SQLException {
        con.setAutoCommit(false);
        PreparedStatement stmt = con.prepareStatement("insert into S (sid,sname,status) values (?,?,?)");
        for (int i = 0; i < nRecords; i++) {
            stmt.setString(1, "S" + i);
            stmt.setString(2, "SN" + i);
            stmt.setInt(3, 1);
            stmt.execute();
        }
        stmt.close();
        con.commit();
    }

    /**
     * 選擇數(shù)據(jù)
     * @throws SQLException
     */
    void select() throws SQLException {
        con.setAutoCommit(true);
        PreparedStatement pstmt = con.prepareStatement("select sid,sname,status from S where sid=?");
        System.out.println("SID\tSNAME\tStatus");
        for (int i = 0; i < nRecords; i++) {
            pstmt.setString(1, "S" + i);
            ResultSet result = pstmt.executeQuery();
            while (result.next()) {
                System.out.println(result.getString(1) + "\t" + result.getString(2) + "\t" + result.getInt(3));
            }
        }
        pstmt.close();
        System.out.println("--------------");
    }

    /**
     * 更新數(shù)據(jù)
     * @throws SQLException
     */
    void update() throws SQLException {
        PreparedStatement pstmt = con.prepareStatement("update S set status=? where sid=?");
        for (int i = 0; i < nRecords; i++) {
            pstmt.setInt(1, i);
            pstmt.setString(2, "S" + i);
            pstmt.execute();
        }
        pstmt.close();

        System.out.println("SID\tStatus\n");
        Statement stmt = con.createStatement();
        ResultSet result = stmt.executeQuery("select sid,status from S order by sid desc");
        while (result.next()) {
            System.out.println(result.getString(1) + "\t" + result.getInt(2));
        }
        stmt.close();
    }

    /**
     * 刪除數(shù)據(jù)
     * @throws SQLException
     */
    void delete() throws SQLException {
        Statement stmt = con.createStatement();
        int nDeleted = stmt.executeUpdate("delete from S");
        System.out.println("Remove " + nDeleted + " records");
    }
}

3.5 運行結(jié)果

4 C語言操作示例

4.1 創(chuàng)建數(shù)據(jù)庫模式文件 simpledb.mco

declare database simpledb;

struct B {
    signed<1> i1;
    signed<2> i2;
    signed<4> i4;
    float     f;  
    char<10>  c10;
};

class A {
    unsigned<1>   ui1;
    unsigned<2>   ui2;
    unsigned<4>   ui4;
    double        d;
    numeric<10,3> num;
    decimal<10,3> dec; 
    B             b;
    string        s;
    
    list;
};

4.2 編譯數(shù)據(jù)庫模式文件

進入/host/bin目錄下各吨,執(zhí)行以下指令
mcocomp simpledb.mco
生成數(shù)據(jù)庫相應的頭文件和接口文件simpledb.h和simpledb.c
simpledb.h
simpledb.c

4.3 將mcolib.lib等必要庫文件和上述接口文件加入工程中

4.4 程序處理

  • 打開數(shù)據(jù)庫

  • 連接數(shù)據(jù)庫

  • 操作數(shù)據(jù)庫

  • 關(guān)閉處理

#include <stdio.h>
#include <common.h>
#include <simpledb.h>

const char * db_name = "operations";

int main(int argc, char* argv[]) {
    
  MCO_RET         rc;
  sample_memory_t dbmem;

  sample_os_initialize(DEFAULT);

  // 1.開啟數(shù)據(jù)庫運行環(huán)境
  mco_runtime_start();

  sample_header("Sample 'operations' performs basic insert, read, and update operations.\n" );
  // 2.打開數(shù)據(jù)庫
  rc = sample_open_database( db_name, simpledb_get_dictionary(), DATABASE_SIZE, CACHE_SIZE, 
                             MEMORY_PAGE_SIZE, PSTORAGE_PAGE_SIZE, 1, &dbmem );
                               
  sample_rc_check("\tOpen", rc );

  if ( MCO_S_OK == rc ) { // 2.1 若數(shù)據(jù)庫打開成功

    mco_db_h connection; /* 數(shù)據(jù)庫連接句柄 */

    // 3.連接數(shù)據(jù)庫
    rc = mco_db_connect( db_name, &connection );
    sample_rc_check("\tConnect", rc );
    
    if ( MCO_S_OK == rc ) {  // 3.1 若數(shù)據(jù)庫連接成功
    
      mco_trans_h t; /* 事務句柄 */
     
      // 4.開啟寫事務,向數(shù)據(jù)庫中插入數(shù)據(jù)
      rc = mco_trans_start(connection, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
      sample_rc_check("\tOpen Transaction", rc );
      if ( MCO_S_OK == rc ) {     // 4.1 若事務開啟成功  
        A        a;   /* Object handle */
        A_fixed _a;   /* Fixed size part of class A */
        B        b;   /* Struct handle */
        B_fixed _b;   /* Fixed size part of struct B */
        uint1  ui1;   /* Value place holders */
        uint2  ui2;
        uint4  ui4;
        int1   i1;
        int2   i2;
        int4   i4;
        mco_int8   i8;
        float  f = (float)1.1;
        double d = 2.2;
        char   buf[16]; /* String buffer */
        mco_cursor_t csr; /* 游標 */
         
        /* 5.創(chuàng)建對象蜒程,向?qū)ο笾懈鲗傩再x值*/
        A_new ( t, &a );

        /* Put values to scalar fields */
        A_ui1_put ( &a, 1 );
        A_ui2_put ( &a, 2 );
        A_ui4_put ( &a, 3 );
        A_d_put   ( &a, d );
         
        /* Put value to string field using db_name as a value */
        A_s_put   ( &a, db_name, (uint2)strlen( db_name ) );

        /* Put int8 value to numeric field */
        A_num_from_chars( &i8, "1234567");
        A_num_put ( &a, i8 );

        /* Put char array value to decimal field */
        A_dec_to_chars( 987654321, buf, sizeof(buf));
        A_dec_put_chars( &a, buf );

        /* Get struct handle to write it */
        A_b_write_handle ( &a, &b );
         
        /* Put values to the struct fields */
        B_i1_put ( &b, 4 );
        B_i2_put ( &b, 5 );
        B_i4_put ( &b, 6 );
        B_f_put  ( &b, f );
        B_c10_put( &b, db_name, (uint2)strlen( db_name ) );
        // 6.提交事務
        rc = mco_trans_commit( t );
        sample_rc_check("\tCommit Transaction", rc );

        // 7.開啟一個讀事務
        rc = mco_trans_start(connection, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &t);

        if ( MCO_S_OK == rc ) { // 7.1 若事務開啟成功  
          rc = A_list_cursor(t, &csr); // 8.創(chuàng)建list遍歷的游標
          if ( MCO_S_OK == rc ) { 
            mco_cursor_first(t, &csr);   // 9.游標置開始
            A_from_cursor(t, &csr, &a);  // 10.游標遍歷數(shù)據(jù)庫對象
            printf("\n\tContents of first record A: \n");
            // 11.從數(shù)據(jù)庫中獲取值绅你,并賦值給變量
            /* Get values from the object fields */
            A_ui1_get ( &a, &ui1 );
            A_ui2_get ( &a, &ui2 );
            A_ui4_get ( &a, &ui4 );
            A_d_get   ( &a, &d );
            printf("\t\tui1=%d, ui2=%d, ui4=%ld, d=%f\n", ui1, ui2, ui4, d );
            /* Get values from numeric/decimal fields */
            A_num_get( &a, &i8);
            A_num_get_chars( &a, buf, sizeof(buf));
            printf("\t\tnum=%lld, chars(%s)\n", i8, buf );
            A_dec_get( &a, &i8);
            A_dec_get_chars( &a, buf, sizeof(buf));
            printf("\t\tdec=%lld, chars(%s)\n", i8, buf );
            /* Get string value into the buf and the value length into ui2 */
            /* Note: the _get() will null-terminate the string only if the buffer is long enough */
            A_s_get( &a, buf, sizeof(buf), &ui2);
            printf("\tstring s=(%s), (length = %d)\n", buf, ui2);

            /* Get struct read-handle */
            A_b_read_handle  ( &a, &b );

            /* Get values of the structs fields */
            B_i1_get ( &b, &i1 );
            B_i2_get ( &b, &i2 );
            B_i4_get ( &b, &i4 );
            B_f_get  ( &b, &f );
            B_c10_get( &b, buf, sizeof(buf) );
            printf("\tStruct b: b.i1=%d, b.i2=%d, b.i4=%ld, b.f=%f, b.c10=(%s)\n", i1, i2, i4, f, buf );

            /* Get field values from A_fixed */
            printf("\n\tUsing A_fixed :\n" );
            A_fixed_get(&a, &_a);
            printf("\t\t_a.ui1=%d, _a.ui2=%d, _a.ui4=%ld, _a.d=%f\n", _a.ui1, _a.ui2, _a.ui4, _a.d );
            
            /* Get field values from B_fixed */
            printf("\n\tUsing B_fixed :\n" );
            B_fixed_get(&b, &_b);
            /* Copy and null terminate the character string in _b.c10 */
            strncpy(buf, _b.c10, 10);
            printf("\t\t_b.i1=%d, _b.i2=%d, _b.i4=%ld, _b.f=%f, _b.c10=(%s)\n", _b.i1, _b.i2, _b.i4, _b.f, buf );

          }
        }
        // 12.提交事務
        rc = mco_trans_commit( t );
      }
       
      /* 13.關(guān)閉數(shù)據(jù)庫連接 */
      rc = mco_db_disconnect( connection );
      sample_rc_check("\tDisconnect", rc );
    }

    /* 14.關(guān)閉數(shù)據(jù)庫 */
    sample_close_database( db_name, &dbmem );
    sample_rc_check("\tClose", rc );
  }
  
  /* 15.關(guān)閉運行環(huán)境 */
  mco_runtime_stop();
     
  sample_pause_end("\n\nPress any key to continue . . . ");

  sample_os_shutdown();

  return ( MCO_S_OK == rc ? 0 : 1 );
}

4.5 運行結(jié)果

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市昭躺,隨后出現(xiàn)的幾起案子忌锯,更是在濱河造成了極大的恐慌,老刑警劉巖领炫,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件偶垮,死亡現(xiàn)場離奇詭異,居然都是意外死亡帝洪,警方通過查閱死者的電腦和手機似舵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來葱峡,“玉大人砚哗,你說我怎么就攤上這事∨檗龋” “怎么了蛛芥?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長军援。 經(jīng)常有香客問我仅淑,道長,這世上最難降的妖魔是什么胸哥? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任涯竟,我火速辦了婚禮,結(jié)果婚禮上空厌,老公的妹妹穿的比我還像新娘庐船。我一直安慰自己,他們只是感情好嘲更,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布醉鳖。 她就那樣靜靜地躺著,像睡著了一般哮内。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天北发,我揣著相機與錄音纹因,去河邊找鬼。 笑死琳拨,一個胖子當著我的面吹牛瞭恰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狱庇,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼惊畏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了密任?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤缰盏,失蹤者是張志新(化名)和其女友劉穎淹遵,沒想到半個月后透揣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年恨闪,在試婚紗的時候發(fā)現(xiàn)自己被綠了放坏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淤年。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡麸粮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出愚战,到底是詐尸還是另有隱情,我是刑警寧澤塔插,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布想许,位于F島的核電站断序,受9級特大地震影響违诗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碉哑,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一扣典、第九天 我趴在偏房一處隱蔽的房頂上張望贮尖。 院中可真熱鬧趁怔,春花似錦润努、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倚聚。三九已至惑折,卻和暖如春枯跑,著一層夾襖步出監(jiān)牢的瞬間矗积,已是汗流浹背棘捣。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工乍恐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留测砂,地道東北人砌些。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓存璃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纵东。 傳聞我的和親對象是個殘疾皇子偎球,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容