SQLite全面解析附封装源码模板文档格式.docx
- 文档编号:22433671
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:17
- 大小:36.51KB
SQLite全面解析附封装源码模板文档格式.docx
《SQLite全面解析附封装源码模板文档格式.docx》由会员分享,可在线阅读,更多相关《SQLite全面解析附封装源码模板文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
有这些公司的参与,对SQLite的发展应该有很大的帮助,尤其是像Google这样的用户。
2、实现与应用
下面从实现及应用的角度来谈谈SQLite,先看看SQLite的特点(功能)吧。
特点
简单(simple):
SQLite是一个非常轻量级自包含(lightweightandself-contained)的DBMS:
一个头文件,一个动态库文件,你就拥有了关系数据库的所有功能了。
简单,是SQLite最明显的哲学。
它提供的API少而简单。
只需要一个DLL文件,你的程序马上就拥有了一个功能强大的数据库引擎,这是一件很美妙的事。
小巧(small):
我用VS2005在Windows下编译的3.6.11,Release版为368K,用时不到20秒——而编译MySQL时,要花上几分钟。
而当我插入10000条int数据时,内存开销660K,磁盘开销92K。
事务(transaction):
事务是现代商业数据处理系统最基本的要求,而Access,不论是在可执行文件大小(看了一下Access2003的可执行文件大小为6.32M,两者不是一个量级),还是事务特性,都是不能和SQLite相比的。
并发性(Concurrency):
由于SQLite通过OS的文件锁来实现库级锁,粒度很大,但是,它通过一些复杂特殊的处理(具体可以参见分析系列),尽量的提升了读写的并发度。
如果你还有担心,你可以看看这篇文章:
SQL92:
SQLite支持绝大部分的标准SQL语句,你只需要几百K的空间,就可以换来需要上百兆的通用DBMS几乎所有操作了。
方便(Convenience):
如果你的程序要使用SQLite,只需要将拷贝你的程序目录即可。
开源(Opensource):
这是它最强大的地方。
开源,意味着你可以品读它的源码,你可以随时修改它,加入你自己的特性,而这一切完全免费的。
开源,是一种精神。
实现部分
好了,现在从实现的角度来谈谈个人体会,这也是我比较关注的。
SQLite是一款优秀的嵌入式数据库管理系统,这里有两层含义:
一是它经常作为动态库嵌入到应用程序;
另外一方面它通常用于嵌入式设备或其它要求较低的桌面应用。
如果把它作为内存数据库,个人觉得不是很适合。
毕竟,它的写并发性不是很好,此时,TimesTen也许会更好,BerkeyDB也许是一个不错的选择。
SQLite这样的嵌入式数据库与主存数据库的应用场景、实现以及对资源的需求都是不一样的。
(1)事务处理
事务的核心问题有两个:
并发控制和恢复。
解决了并发控制和恢复问题的系统,就能允许它的用户假设程序是原子的(atomically)执行的——好像没有其它的程序同时执行;
而且是可靠的(reliably)——不会产生失败。
原子性和可靠性的抽象,则称为事务(transaction)。
其实,事务并不是DBMS的专利,任何分布式系统,都面对并发和恢复问题,而解决的方法就是事务,只不过,我们更常听到DBMS中的事务。
并发控制保证事务的原子执行,它使得交错执行的事务看起来是一个接一个的顺序执行的,完全没有交错执行。
如果交错执行的结果与顺序执行的结果一致,则称为串行化(serializable)。
恢复使得数据库仅仅包含那些正常完成的事务的结果。
如果事务在执行的过程中发生错误,不能继续进行,恢复算法必须清除部分完成事务产生的影响。
并发控制
SQLite只支持库级锁,库级锁意味着什么?
——意味着同时只能允许一个写操作,也就是说,即事务T1在A表插入一条数据,事务T2在B表中插入一条数据,这两个操作不能同时进行,即使你的机器有100个CPU,也无法同时进行,而只能顺序进行。
表级都不能并行,更别说元组级了——这就是库级锁。
但是,SQLite尽量延迟申请X锁,直到数据块真正写盘时才申请X锁,这是非常巧妙而有效的。
恢复
SQLite的恢复技术是影子分页技术(shadowpaging)技术的典型代表。
DBMS的常用恢复技术有影子分页技术与基于日志的技术,前者在早其数据库管理系统中用到,比如SystemR,现代DBMS中已经很难见到它的身影了。
影子分页技术与基于日志技术相比,优点是实现简单,消除了写日志记录的开销,恢复的速度也快(不需要redo和undo)。
影子分页的缺点就是事务提交时要输出多个块,这使得提交的开销很大,而且以块为单位,很难应用到允许多个事务并发执行的情况——这是它致命的缺点。
(2)查询处理
SQLite的查询处理本质上就是一个SQL编译器和一个虚拟机。
而实现这些功能只用了十多个文件,整个实现实现简单而有效,但是也存在一些问题。
首先,SQLite字典数据很简单,实际上它的字典就一个表sqlite_mater,所有的信息都是通过对sqlite_master中SQL语句进行解析获取的,而解析一个SQL语句,都需要进行词法分析、语法分析、甚至虚拟机代码的生成。
而这一过程是很需要时间的,而且,查询计划也没有重用。
其次,查询优化还比较简单,特别是连接操作,只通过循环来做(MySQL也一样)。
但是,仅仅数万代码,我们不能对它要求太苛求。
(3)存储模型
SQLite的文件物理上被划分成相同大小的块;
逻辑上划分成一些B-Tree——每个表对应一个B-Tree。
而没有像Oracle,或者InnoDB对数据块进行复杂的逻辑组织,这种按需分配数据块的做法必然影响磁盘的读写性能。
不过,归根到底,还是源于它的应用场景。
(4)缓冲区管理
Buffer的管理对于DBMS,无疑是非常重要的,SQLite在其它方面做得比较简单,但是在缓冲区管理这一块,它还是做足了功夫。
SQLite采用DBMS常用的LRU算法。
更值得一提的是,在较新的版本中,SQLite采用和虚拟文件系统的类似的方式,实现了让默认缓冲区管理子系统可以很容易的切换成其它的缓冲区管理算法,这是非常灵活的。
(5)I/O
SQLite采用简单的阻塞I/O,较新的版本将异步I/O作为可选的扩展,但是,由于SQLite没有日志,所以,事务中ACID中的D,就无法保证,所以,如果你的数据很关键,请不要用SQLite的异步I/O。
另一方面,实际上,很多嵌入式操作系统,比如WindowsCE并不支持异步I/O(不过,这可以通过多线程加以解决)。
但是,这些“缺点”并不是SQLite的缺点,相对于通过DBMS,恰恰是它的优点,这样的实现简单,而且对资源的需求较低。
对嵌入式设备、或者那些要求较低的应用,已经足够,足够就好。
应用场景
嵌入式设备:
这应该是SQLite应用的主要场景,很多公司都在他们的嵌入式应用程序中使用SQLite,其中不乏google的Android。
桌面应用:
如果你已经厌恶了fopen,fread,fwrite这些函数,SQLite是你不错的选择,它接口简单,而且支持事务。
前些天无意中下了一个cookie清除软件——CookieCrumbler,打开一看,发现里面竟然有一个sqlite3.dll,着实让我震惊了一把。
Websites:
如果你的站点的访问量、数据量小的个人站点,SQLite可以代替开销较大的MySQL和繁杂的Access。
最近因为学校那个项目,也在搞数据库方面的东西,以前也用过SQLITE的东西,拿来复习下
Sqlite是一个面向嵌入式系统的数据库,编译完成只有200K,同时支持2T的数据记录。
对于嵌入式设备是一个很好的数据库引擎。
本文通过一个小例子说明如何在C与C++调用SqliteAPI完成数据库的创建、插入数据与查询数据。
本文的开发环境为(Redhat9.0+Qtopia2.1.2+Sqlite3)
安装Sqlite3:
从www.sqlite.org上下载Sqlite3.2.2运源代码,依照Readme中的步骤:
tarxzfsqlite3.2.2.tar.gz
mkdirbld
cdbld
../sqlite3.2.2/configure
make
makeinstall
然后在shell下运行sqlite3test.db命令可以检验是否已经安装成功。
创建数据库:
sqlite3*pDB=NULL;
char*errMsg=NULL;
//打开一个数据库,如果改数据库不存在,则创建一个名字为databaseName的数据库文件
intrc=sqlite3_open(databaseName,&
pDB);
if(rc)
{
cout<
<
"
Openthedatabase"
<
databaseName<
failed"
endl;
}
//如果创建成功,添加表
else
createthedatabasesuccessful!
"
//creatthetable
inti;
for(i=1;
i<
nTableNum;
i++)
//插入一个表,返回值为SQLITE_OK为成功,否则输出出错信息
//函数参数:
第一个为操作数据库的指针,第二句为SQL命令字符串
//第三个参数为callback函数,这里没有用,第四个参数为callback函数
//中的第一个参数,第五个为出错信息
rc=sqlite3_exec(pDB,"
CREATETABLEchn_to_eng(chineseQString,englishQString)"
0,0,&
errMsg);
if(rc==SQLITE_OK)
createthechn_to_engtablesuccessful!
errMsg<
//同上,插入另一个表
CREATETABLEeng_to_chn(englishQString,chineseQString)"
createtheeng_to_chntablesuccessful!
、、、、、、
//往表中添加数据
charchn[]="
..."
;
chareng[]="
charvalue[500];
//定义一条参数SQL命令,其中chn,eng为需要插入的数据
sprintf(value,"
INSERTINTOchn_to_eng(chinese,english)VALUES('
%s'
'
)"
chn,eng);
//usetheSQLITEC/C++APItocreateandadjustadatabase.
rc=sqlite3_exec(pDB,
value,
0,0,&
//查询一条记录
//定义一条查询语句,其中条件为当english为target时的中文记录
//print_result_cb为callback函数,在其中可以得到查询的结果,具体见下文
SELECTchineseFROMeng_to_chnwhereenglish='
target);
print_result_cb,0,&
//
#ifdef_debug
selecttherecordsuccessful!
#endif
returnfalse;
.......
//callback回调函数print_result_cb的编写,其中data为sqlite3_exec中的第四个参数,第二个参数是栏的数目,第三个是栏的名字,第四个为查询得到的值得。
这两个函数输出所有查询到的结果
intprint_result_cb(void*data,intn_columns,char**column_values,
char**column_names)
staticintcolumn_names_printed=0;
if(!
column_names_printed){
print_row(n_columns,column_names);
column_names_printed=1;
print_row(n_columns,column_values);
return0;
voidprint_row(intn_values,char**values)
for(i=0;
i<
n_values;
++i){
if(i>
0){
printf("
t"
);
%s"
values[i]);
n"
大致过程就是如此,具体可以参考SQLITE的API函数说明,见www.sqlite.org
&
nbsp;
//查询一条记录
大致过程就是如此,具体可以参考SQ
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SQLite 全面 解析 封装 源码 模板