自几十年前出现的商业应用程序以来,数据库就成为软件应用程序的主要组成部分。正与数据库管理系统非常关键一样,它们也变得非常庞大,并占用了相当多的系统资源,增加了管理的复杂性。随着软件应用程序逐渐模块模块化,一种新型数据库会比大型复杂的传统数据库管理系统更适应。嵌入式数据库直接在应用程序进程中运行,提供了零配置(zero-configuration)运行模式,并且资源占用非常少。本文将介绍流行的 SQLite 数据库引擎,并描述如何在应用程序开发中使用它。
SQLite 是 D. Richard Hipp 用 C 语言编写的开源嵌入式数据库引擎。它是完全独立的,不具有外部依赖性。它是作为 PHP V4.3 中的一个选项引入的,构建在 PHP V5 中。SQLite 支持多数 SQL92 标准,可以在所有主要的操作系统上运行,并且支持大多数计算机语言。SQLite 还非常健壮。其创建者保守地估计 SQLite 可以处理每天负担多达 100,00 次点击率的 Web 站点,并且 SQLite 有时候可以处理 10 倍于上述数字的负载。
SQLite 对 SQL92 标准的支持包括索引、限制、触发和查看。SQLite 不支持外键限制,但支持原子的、一致的、独立和持久 (ACID) 的事务(后面会提供有关 ACID 的更多信息)。
|
嵌入式数据库的名称来自其独特的运行模式。这种数据库嵌入到了应用程序进程中,消除了与客户机服务器配置相关的开销。嵌入式数据库实际上是轻量级的,在运行时,它们需要较少的内存。它们是使用精简代码编写的,对于嵌入式设备,其速度更快,效果更理想。嵌入式运行模式允许嵌入式数据库通过 SQL 来轻松管理应用程序数据,而不依靠原始的文本文件。嵌入式数据库还提供零配置运行模式,这样可以启用其中一个并运行一个快照。
要知道,SQLite 的数据库权限只依赖于文件系统,没有用户帐户的概念。SQLite 有数据库级锁定,没有网络服务器,并且可以实现多数 SQL92 标准(但不是全部)。SQL92 标准的其他一些主要功能是外键和检查限制。了解哪些 未实现。 | |
这意味着事务是原子的,因为它们要么完全执行,要么根本不执行。事务也是一致的,因为在不一致的状态中,该数据库从未被保留。事务还是独立的,所以,如果在同一时间在同一数据库上有两个执行操作的事务,那么这两个事务是互不干扰的。而且事务是持久性的,所以,该数据库能够在崩溃和断电时幸免于难,不会丢失数据或损坏。
SQLite 通过数据库级上的独占性和共享锁定来实现独立事务处理。这意味着当多个进程和线程可以在同一时间从同一数据库读取数据,但只有一个可以写入数据。在某个进程或线程向数据库执行写入操作之前,必须获得独占锁定。在发出独占锁定后,其他的读或写操作将不会再发生。
SQLite 网站上记录了完整的 。
在内部,SQLite 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 SQLite 的内核变得更加方便。所有 SQL 语句都被编译成易读的、可以在 SQLite 虚拟机中执行的程序集。
SQLite 支持大小高达 2 TB 的数据库,每个数据库完全存储在单个磁盘文件中。这些磁盘文件可以在不同字节顺序的计算机之间移动。这些数据以 B+树(B+tree)数据结构的形式存储在磁盘上。SQLite 根据该文件系统获得其数据库权限。
SQLite 不支持静态数据类型,而是使用列关系。这意味着它的数据类型不具有表列属性,而具有数据本身的属性。当某个值插入数据库时,SQLite 将检查它的类型。如果该类型与关联的列不匹配,则 SQLite 会尝试将该值转换成列类型。如果不能转换,则该值将作为其本身具有的类型存储。
SQLite 支持 NULL
、INTEGER
、REAL
、TEXT
和 BLOB
数据类型。
SQLite 附带一个可下载的 。通过数据库名称可以调用此命令行程序,并且可以按照下面的方式创建新的数据库和表:
C:\minblogg>sqlite3 c:\minblogg\www\db\alf.db
SQLite version 3.2.1
Enter ".help" for instructions
sqlite> create table mytable(name varchar(40), age smallint);
sqlite> insert into mytable values('Nils-Erik',23);
sqlite> select * from mytable;
Nils-Erik|23
sqlite>
|
然后,可以再次打开该数据库,列出它的表和架构,并继续进行插入和删除值的操作。
C:\minblogg>sqlite3 c:\minblogg\www\db\alf.db
SQLite version 3.2.1
Enter ".help" for instructions
sqlite> .tables
mytable
sqlite> select * from mytable;
Nils-Erik|23
sqlite> .schema
CREATE TABLE mytable(name varchar(40), age smallint);
sqlite>
|
SQLite 还附带命令行数据库分析器,该分析器允许您显示关于任何 SQLite 数据库当前状态的详细信息。
C:\minblogg>sqlite3_analyzer www\db\alf.db
Analyzing table mytable...
Analyzing table sqlite_master...
/** Disk-Space Utilization Report For www\db\alf.db
*** As of 2005-Apr-24 18:56:40
Page size in bytes.................... 1024
Pages in the whole file (measured).... 2
Pages in the whole file (calculated).. 2
Pages that store data................. 2 100.0%
Pages on the freelist (per header).... 0 0.0%
Pages on the freelist (calculated).... 0 0.0%
Pages of auto-vacuum overhead......... 0 0.0%
Number of tables in the database...... 2
Number of indices..................... 0
Number of named indices............... 0
Automatically generated indices....... 0
Size of the file in bytes............. 2048
Bytes of user payload stored.......... 13 0.63%
*** Page counts for all tables with their indices ********************
MYTABLE............................... 1 50.0%
SQLITE_MASTER......................... 1 50.0%
*** All tables *******************************************************
Percentage of total database.......... 100.0%
Number of entries..................... 2
Bytes of storage consumed............. 2048
Bytes of payload...................... 91 4.4%
Average payload per entry............. 45.50
Average unused bytes per entry........ 916.50
Maximum payload per entry............. 78
Entries that use overflow............. 0 0.0%
Primary pages used.................... 2
Overflow pages used................... 0
Total pages used...................... 2
Unused bytes on primary pages......... 1833 89.5%
Unused bytes on overflow pages........ 0
Unused bytes on all pages............. 1833 89.5%
*** Table MYTABLE ****************************************************
Percentage of total database.......... 50.0%
Number of entries..................... 1
Bytes of storage consumed............. 1024
Bytes of payload...................... 13 1.3%
Average payload per entry............. 13.00
Average unused bytes per entry........ 999.00
Maximum payload per entry............. 13
Entries that use overflow............. 0 0.0%
Primary pages used.................... 1
Overflow pages used................... 0
Total pages used...................... 1
Unused bytes on primary pages......... 999 97.6%
Unused bytes on overflow pages........ 0
Unused bytes on all pages............. 999 97.6%
|
由于完全能够使用命令行界面来管理数据库,因此它可以为数据库管理员带来很大的方便。目前有许多优秀的基于 Web 的 SQLite 数据库管理系统。其中有一个是基于 PHP 的 。
备份 SQLite 数据库有两种方法。如果数据库正在使用中,则应从命令行界面使用 .dump 命令。这样可以创建一个包含必要命令和数据的文件,从而重新创建数据库。.dump
命令也可以用于备份数据库表。
sqlite> .dump
BEGIN TRANSACTION;
CREATE TABLE mytable(name varchar(40), age smallint);
INSERT INTO "mytable" VALUES('Nils-Erik', 23);
COMMIT;
sqlite>
|
如果数据库没有处于使用状态,则可以直接将数据库文件复制到安全位置。
一个好的做法是将 SQLite 数据库与 PHP 代码分开。完成此操作的一个简便方法是创建一个 www 目录。在此目录中,创建一个用于存放 SQLite 数据库的 db 目录、一个用于存放数据库和表创建脚本的 dbscripts 目录和一个用于存放数据库备份的 backups 目录。
2004-12-06 15:43 DIR .
2004-12-06 15:43 DIR ..
2005-04-23 19:55 DIR db
2005-01-02 11:46 DIR dbscripts
2005-01-02 11:46 DIR backups
|
在 PHP V5 中创建 SQLite 数据库与在命令行界面中创建该数据库非常相似。如果该数据库不存在,则创建一个空数据库。
$db = sqlite_open('../db/ac.db');
|
创建一个表也非常容易:
$db = sqlite_open('../db/ac.db');
sqlite_query($db, 'DROP TABLE post');
sqlite_query($db, 'CREATE TABLE post (id INTEGER PRIMARY KEY, kategori VARCHAR(20) NOT NULL,
titel VARCHAR(75) NOT NULL, referens VARCHAR(75), status VARCHAR(20) not null,
date varchar(10)not null, synopsis VARCHAR(120), inlaegg varchar(8192))');
|
插入一条记录:
$sqldb = sqlite_open("../db/ac.db");
sqlite_query($sqldb, "INSERT INTO isvs VALUES ('$isvurl' , '$isvname', '$comment')");
|
并选择数据:
$sqldb = sqlite_open("www/db/ac.db");
$results = sqlite_query($sqldb, "SELECT * FROM isvs order by isvurl asc ");
while (list($isvurl, $isvname) = sqlite_fetch_array($results)) {
sqlite_close($sqldb);
|
两个先进的开源数据库抽象层对 SQLite 提供支持:PEAR::DB,它们包含在 PHP V5 中,并且被认为是更轻量级的 ezSQL。通过预先使用 PHP 扩展和应用程序库 (PEAR) 或 ezSQL,可将 SQLite 用于应用程序的快速复原,在以后需要时,可以将其无缝转向更具工业性质的数据库。
$users = $db->get_results("SELECT name, age FROM table1");
foreach ( $users as $user )
{
echo $user->name;
echo $user->age;
}
|
|
SQLite 不是惟一的开源嵌入式数据库引擎。如果 SQLite 不能满足您的要求,请使用 Derby(是 Apache 孵化器项目)和 (IBM 公司的 Derby 商业版本,包括 IBM 支持和服务)。Cloudscape 于 1996 年诞生于 Cloudscape 公司。三年以后,Informix 软件公司并购了 Cloudscape,2001 年,IBM 并购了 Informix 软件公司的数据库资产,其中包括 Cloudscape。去年,IBM 将此代码像 “Derby”一样作为孵化器项目献给了 Apache Software Foundation。
Derby 是100 % 的 Java 编程语言关系数据库,并提供了存储过程和触发器,行级锁定,可以执行事务提交和回退操作,并支持加密。
最近,Zend 公司为 IBM 发布了 Zend Core,该软件可以看作是基于 PHP V5 的解决方案,其中包括用于 Cloudscape 的 PHP 扩展和绑定的 Cloudscape 数据库服务器。 | |
在确定是否在应用程序中使用 SQLite 之前,应该考虑以下几种情况:
- 目前没有可用于 SQLite 的网络服务器。从应用程序运行位于其他计算机上的 SQLite 的惟一方法是从网络共享运行。这样会导致一些问题,像 UNIX® 和 Windows® 网络共享都存在文件锁定问题。还有由于与访问网络共享相关的延迟而带来的性能下降问题。
- SQLite 只提供数据库级的锁定。虽然有一些增加并发的技巧,但是,如果应用程序需要的是表级别或行级别的锁定,那么 DBMS 能够更好地满足您的需求。
- 正如前面提到的,SQLite 可以支持每天大约 100,00 次点击率的 Web 站点 —— 并且,在某些情况下,可以处理 10 倍于此的通信量。对于具有高通信量或需要支持庞大浏览人数的 Web 站点来说,应该考虑使用 DBMS。
- SQLite 没有用户帐户概念,而是根据文件系统确定所有数据库的权限。这会使强制执行存储配额发生困难,强制执行用户许可变得不可能。
- SQLite 支持多数(但不是全部)的 SQL92 标准。不受支持的一些功能包括完全触发器支持和可写视图。请参阅 。
如果您感到其中的任何限制会影响您的应用程序,那么您应该考虑使用完善的 DBMS。如果您可以解除这些限制问题,并且对快速灵活的嵌入式开源数据库引擎很感兴趣,则应重点考虑使用 SQLite。
一些能够真正表现 SQLite 优越性能的领域是 Web 站点,可以使用 SQLite 管理应用程序数据、快速应用程序原型制造和培训工具。
由于资源占用少、性能良好和零管理成本,嵌入式数据库有了它的用武之地,它将为那些以前无法提供用作持久数据的后端的数据库的应用程序提供了高效的性能。现在,没有必要使用文本文件来实现持久存储。SQLite 之类的嵌入式数据库的易于使用性可以加快应用程序的开发,并使得小型应用程序能够完全支持复杂的 SQL。这一点对于对于小型设备空间的应用程序来说尤其重要。
嵌入式数据库对于加快应用程序开发也很重要,尤其是在用于数据库抽象层(例如 或 )时。最后,SQLite 正在积极开发中,未来一定会有新的功能,会对开源社区更有用。