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é)果