什么是 SQLite
SQLite是一款轻量级的、基于文件的嵌入式数据库,实现自包容、零配置、支持事务的SQL数据库引擎。与其他数据库管理系统不同,SQLite 的安装和运行非常简单,在大多数情况下,只要确保SQLite的二进制文件存在即可开始创建、连接和使用数据库。第一个Alpha版本诞生于2000年5月,直到今天已经成为最流行的嵌入式数据库,包括Google在内的许多公司在其桌面软件中亦使用SQLite存储用户数据,由此看来,其稳定性毋庸置疑。
实际应用中,SQLite作为目前最为流行的开源嵌入式关系型数据库,在系统的架构设计中正扮演着越来越重要的角色。和很多其它嵌入式NoSQL数据库(如BerkeleyDB、MemBASE等)不同的是,SQLite支持很多关系型数据库的基本特征,如标准SQL语法、事务、数据表和索引等,这在数据移植、程序演示等应用中有着不可替代的优势。从官方文档中我们可以获悉到,SQLite支持的数据量和运行效率都是非常骄人的,因此在海量数据的解决方案中,SQLite可以作为数据预计算的桥头堡,从而显著减少存储在关系型数据库服务器中的数据数量,最终提高系统的查询效率和运行期效率,同时也可以显著的降低数据备份的磁盘开销。
SQLite的主要特征:
1). 管理简单,甚至可以认为无需管理。
2). 操作方便,SQLite生成的数据库文件可以在各个平台无缝移植。
3). 可以非常方便的以多种形式嵌入到其他应用程序中,如静态库、动态库等。
4). 易于维护。
综上所述,SQLite的主要优势在于灵巧、快速和可靠性高。SQLite的设计者们为了达到这一目标,在功能上作出了很多关键性的取舍,与此同时,也失去了一些对RDBMS关键性功能的支持,如高并发、细粒度访问控制(如行级锁)、丰富的内置函数、存储过程和复杂的SQL语句等。正是因为这些功能的牺牲才换来了简单,而简单又换来了高效性和高可靠性。
SQLite的优势
① 免配置。和Access一样,只要把数据库文件通过FTP上传到服务器上即可使用,不需要服务器的额外支持。
② 备份方便。因为只是一个文件,只要复制一份该文件,就能备份整个数据库。
③ 虽然是轻量级数据库。但最大能支持2TB 大小的单个库文件。
④ 速度快。在几百万条记录的情况下,其插入和查询速度与MySQL不分上下,快于SQL Server,10倍于Access(但这并不意味着它可以替代SQL Server)。
SQLite的主要优点
1. 一致性的文件格式:
在SQLite的官方文档中是这样解释的,我们不要将SQLite与Oracle或PostgreSQL去比较,而是应该将它看做fopen和fwrite。与我们自定义格式的数据文件相比,SQLite不仅提供了很好的移植性,如大端小端、32/64位等平台相关问题,而且还提供了数据访问的高效性,如基于某些信息建立索引,从而提高访问或排序该类数据的性能,SQLite提供的事务功能,也是在操作普通文件时无法有效保证的。
2. 在嵌入式或移动设备上的应用:
由于SQLite在运行时占用的资源较少,而且无需任何管理开销,因此对于PDA、智能手机等移动设备来说,SQLite的优势毋庸置疑。
3. 内部数据库:
在有些应用场景中,我们需要为插入到数据库服务器中的数据进行数据过滤或数据清理,以保证最终插入到数据库服务器中的数据有效性。有的时候,数据是否有效,不能通过单一一条记录来进行判断,而是需要和之前一小段时间的历史数据进行特殊的计算,再通过计算的结果判断当前的数据是否合法。在这种应用中,我们可以用SQLite缓冲这部分历史数据。还有一种简单的场景也适用于SQLite,即统计数据的预计算。比如我们正在运行数据实时采集的服务程序,我们可能需要将每10秒的数据汇总后,形成每小时的统计数据,该统计数据可以极大的减少用户查询时的数据量,从而大幅提高前端程序的查询效率。在这种应用中,我们可以将1小时内的采集数据均缓存在SQLite中,在达到整点时,计算缓存数据后清空该数据。
4. 数据分析:
可以充分利用SQLite提供SQL特征,完成简单的数据统计分析的功能。这一点是CSV文件无法比拟的。
5. 产品Demo和测试:
在需要给客户进行Demo时,可以使用SQLite作为我们的后台数据库,和其他关系型数据库相比,使用SQLite减少了大量的系统部署时间。对于产品的功能性测试而言,SQLite也可以起到相同的作用。
和RDBMS相比,SQLite的劣势
1. C/S应用:
如果你有多个客户端需要同时访问数据库中的数据,特别是他们之间的数据操作是需要通过网络传输来完成的。在这种情况下,不应该选择SQLite。由于SQLite的数据管理机制更多的依赖于OS的文件系统,因此在这种操作下其效率较低。
2. 数据量较大:
受限于操作系统的文件系统,在处理大数据量时,其效率较低。对于超大数据量的存储,甚至不能提供支持。
3. 高并发:
由于SQLite仅仅提供了粒度很粗的数据锁,如读写锁,因此在每次加锁操作中都会有大量的数据被锁住,即使仅有极小部分的数据会被访问。换句话说,我们可以认为SQLite只是提供了表级锁,没有提供行级锁。在这种同步机制下,并发性能很难高效。
SQLite个性化特征
1. 零配置:
SQLite本身并不需要任何初始化配置文件,也没有安装和卸载的过程。当然也不存在服务器实例的启动和停止。在使用的过程中,也无需创建用户和划分权限。在系统出现灾难时,如电源问题、主机问题等,对于SQLite而言,不需要做任何操作。
2. 没有独立的服务器:
和其他关系型数据库不同的是,SQLite没有单独的服务器进程,以供客户端程序访问并提供相关的服务。SQLite作为一种嵌入式数据库,其运行环境与主程序位于同一进程空间,因此它们之间的通信完全是进程内通信,而相比于进程间通信,其效率更高。然而需要特别指出的是,该种结构在实际运行时确实存在保护性较差的问题,比如此时,应用程序出现问题导致进程崩溃,由于SQLite与其所依赖的进程位于同一进程空间,那么此时SQLite也将随之退出。但是对于独立的服务器进程,则不会有此问题,它们将在密闭性更好的环境下完成它们的工作。
3. 单一磁盘文件:
SQLite的数据库被存放在文件系统的单一磁盘文件内,只要有权限便可随意访问和拷贝,这样带来的主要好处是便于携带和共享。其他的数据库引擎,基本都会将数据库存放在一个磁盘目录下,然后由该目录下的一组文件构成该数据库的数据文件。尽管我们可以直接访问这些文件,但是我们的程序却无法操作它们,只有数据库实例进程才可以做到。这样的好处是带来了更高的安全性和更好的性能,但是也付出了安装和维护复杂的代价。
4. 平台无关性:
这一点在前面已经解释过了。和SQLite相比,很多数据库引擎在备份数据时不能通过该方式直接备份,只能通过数据库系统提供的各种dump和restore工具,将数据库中的数据先导出到本地文件中,之后在load到目标数据库中。这种方式存在显而易见的效率问题,首先需要导出到另外一个文件,如果数据量较大,导出的过程将会比较耗时。然而这只是该操作的一小部分,因为数据导入往往需要更多的时间。数据在导入时需要很多的验证过程,在存储时,也并非简简单单的顺序存储,而是需要按照一定的数据结构、算法和策略存放在不同的文件位置。因此和直接拷贝数据库文件相比,其性能是非常拙劣的。
5. 弱类型:
和大多数支持静态类型的数据库不同的是,SQLite中的数据类型被视为数值的一个属性。因此对于一个数据表列而言,即便在声明该表时给出了该列的类型,我们在插入数据时仍然可以插入任意类型,比如Integer的列被存入字符串'hello'。针对该特征唯一的例外是整型的主键列,对于此种情况,我们只能在该列中存储整型数据。
6. SQL语句编译成虚拟机代码:
很多数据库产品会将SQL语句解析成复杂的,相互嵌套的数据结构,之后再交予执行器遍历该数据结构完成指定的操作。相比于此,SQLite会将SQL语句先编译成字节码,之后再交由其自带的虚拟机去执行。该方式提供了更好的性能和更出色的调试能力。
SQLite安装
SQLite on Windows
1)进入 SQL 下载页面:http://www.sqlite.org/download.html
2)下载 Windows 下的预编译二进制文件包:
sqlite-shell-win32-x86-<build#>.zip (注意: <build#> 是 sqlite 的编译版本号) |
- 下载 sqlite-shell-win32-*.zip 和 sqlite-dll-win32-*.zip 压缩文件。
- 创建文件夹sqlite,并在此文件夹下解压上面两个压缩文件,将得到 sqlite3.def、sqlite3.dll 和 sqlite3.exe 文件。
- 添加sqlite 到 PATH 环境变量,以方便在命令行中执行 sqlite 命令。
可选: 如果你计划发布基于 sqlite 数据库的应用程序,你还需要下载源码以便编译和利用其 API。
sqlite-amalgamation-<build#>.zip |
SQLite源码下载
在SQLITE主页https://www.sqlite.org/download.html下载源码,选择出现以下字样的ZIP文件进行下载。
SQLite编译
若要编译SQLite库,需要下载单一文件版本sqlite-amalgamation-3071400.zip。它把sqlite3库的所有源码文件内容放到一个文件sqlite3.c中了(不包含管理工具shell.c),这个文件大概有110000多行,如果除去空白行和注释,则有65000多行的代码!这样做的好处是很容易应用在你的项目中,只需拷贝这一个源文件到你项目中即可。另外,编译器在编译单一的文件时能做一些额外的优化,因为只有一个编译单元。通过测试发现大概有5%-10%的性能提升。
SQLite库可以不编译,直接把单一文件sqlite3.c(或者再加上sqlite3.h)拷贝到你的项目中使用即可。但作为一个单独的库,一般建议编译成独立的二进制文件格式的库,如Linux下的.so动态链接库,Windows下的DLL动态链接库,然后在项目中通过头文件sqlite3.h来使用这个库,这样能使软件更加地模块化。
SQLite3源码在Linux下编译
(1)编译命令行管理工具:gcc shell.c sqlite3.c -lpthread -ldl -o sqlite3 //将生成sqlit3命令行管理工具
(2)编译SQLite为单独的动态链接库:gcc sqlite3.c -lpthread -ldl -fPIC -shared -o libsqlite3.so
-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
-shared:表示生成一个共享目标文件(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),即我们所说的动态链接库。它可以和其他目标文件连接产生可执行文件。只有部分系统支持该选项。
pthread系统库用于确保SQLite是线程安全的。但因为命令行工具是单线程的,对命令行工具则可编译成非线程安全的,以忽略pthread库。命令为gcc -DSQLITE_THREADSAFE=0 shell.c sqlite3.c -ldl -o sqlite3。dl系统库用于支持动态装载,sqlite3_load_extension()接口和SQL函数load_extension()需要用到它。如果不需要这些特性,可以使用SQLITE_OMIT_LOAD_EXTENSION编译选项来忽略,如gcc -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION shell.c sqlite3.c -o sqlite3。
使用动态库libsqlite3.so:在你的程序中(例如test.c)通过包含头文件sqlite3.h来使用库中的函数,编译程序的命令为gcc test.c -L. -lsqlite3 -o test。其中-L.表示让链接库的搜索路径包含当前目录,-lsqlite3指明编译器查找动态库libsqlite3.so,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称。通过ldd test可查看test程序是如何调用动态库中的函数的。
调用动态库时有几个问题会经常碰到。有时明明已经将库的头文件所在目录通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是修改LD_LIBRARY_PATH,这个环境变量指示动态连接器可以装载动态库的路径。或者修改/etc/ld.so.conf文件,然后调用/sbin/ldconfig来达到同样的目的。通常这样做就可以解决库无法链接的问题了。
(3)编译成静态库:gcc -c sqlite3.c -lpthread -ldl -o sqlite3.o //编译成目标文件
ar -r libsqlite3.a sqlite3.o //将列出的各个目标文件一起打包成一个静态库libsqlite3.a
链接静态库:gcc test.c -L. -lsqlite3 -static -o test //也可不加-static选项
SQLite3源码在Windows平台编译
工具:Visual Studio 2010
(1)把SQLite编译成动态链接库:
打开Visual Studio 2010,新建一个名为sqlite3的Visual C++ Win32工程,在工程向导页中选择工程的类型为 "DLL", 并且把创建为空项目的复选框钩上。通过工程--->添加现有项...,把单一文件sqlite3.c添加到工程中。为了生成在链接sqlite3.dll时需要用到的lib文件,需要在工程中添加模块定义文件。根据sqlite3.h中列出的导出函数名,我们可以自己写.def文件,例如:
EXPORTS
sqlite3_aggregate_context
sqlite3_aggregate_count
sqlite3_auto_extension
sqlite3_backup_finish
sqlite3_backup_init
sqlite3_backup_pagecount
sqlite3_backup_remaining
sqlite3_backup_step
sqlite3_bind_blob
sqlite3_bind_double
;......
也可以使用已写好的.def文件,下载已编译好的SQLite DLL库sqlite-dll-win32-x86-3071400.zip,里面有sqlite3.def,把它拷贝到我们的sqlite3项目中,在工程属性的Linker--->Input--->Module Definition File中输入sqlite3.def。设置项目编译成Release版本,编译后生成sqlite3.dll和sqlite3.lib。
编译命令行管理工具:如果想编译出sqlite.exe命令行程序,则需要创建一个空的Win32 控制台程序,然后在往工程里添加文件sqlite3.c和shell.c,直接编译即可。
使用动态链接库sqlite3.dll
新建一个空项目test,把sqlite3.dll, sqlite3.lib, sqlite3.h拷贝到项目目录下,把sqlite3.h添加到项目中。新建主程序源文件test.cpp,如下:
#include <stdio.h> #include "sqlite3.h" #pragma comment(lib,"sqlite3") /* print a record from table outputed by sql statement */ static int callback(void *NotUsed, int argc, char **argv, char **azColName){ int i; for(i=0; i<argc; i++){ printf("%s = %s ", azColName[i], argv[i]?argv[i]:"NULL"); } printf(" "); return 0; } int main(int argc, char **argv){ sqlite3 *db; char *zErrMsg=0; int rc; if(argc!=3){ fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT ", argv[0]); return(1); } rc=sqlite3_open(argv[1],&db); /* open database */ if(rc){ fprintf(stderr, "Can't open database: %s ", sqlite3_errmsg(db)); sqlite3_close(db); return(1); } rc=sqlite3_exec(db,argv[2],callback,0,&zErrMsg); /* execute SQL statement */ if(rc!=SQLITE_OK){ fprintf(stderr,"SQL error: %s ",zErrMsg); sqlite3_free(zErrMsg); } sqlite3_close(db); /* close database */ return 0; }
编译后生成test.exe程序,它的运行依赖于sqlite3.dll。注意程序中也可以不使用pragma指令导入sqlite3.lib,而是在test项目属性中添加对上面的dll项目sqlit3的引用。
这个C程序的例子显示怎么使用sqlite的C/C++接口。数据库的名字由第一个参数取得,第二个参数是一条或更多的SQL执行语句。这个程序调用sqlite3_open()打开指定的数据库,调用sqlite3_exec()对数据库执行SQL语句,callback函数会作用在SQL语句结果集的每条记录上。最后用sqlite3_close()关闭数据库连接。可以用前面的alf.db数据库来测试:test.exe alf.db "select * from mytable"。
(2)把SQLite编译成静态链接库:
新建一个名为sqlite3static,空的Visual C++ Win32工程,在工程向导页中选择工程的类型为 "Static library",去年"Precompiled header"复选框,导入源文件sqlite3.c,编译生成sqlite3static.lib,这是静态链接库版本,它要比动态链接库sqlite3.dll大的多。
使用静态链接库:
新建一个空项目sqlite3statictest,添加对项目sqlite3static的引用,同样使用上面的test.cpp,编译生成sqlite3statictest.exe。可以发现它是一个独立的可执行文件,不依赖静态链接库,删除静态链接库后仍然可以运行。
实际上,静态链接库不存在导出的概念,在链接过程中,静态链接库LIB中的指令都全部被直接包含在最终生成的EXE文件中了,因此如果用的是静态链接库,那么也就不存在“导出某个函数提供给用户使用”的情况。对于使用该静态库的EXE文件来说,直接使用LIB中的函数和全局变量即可,而不管它们有没有导出声明。另外一点在使用中需要注意的是:静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含。
工具:VC++6.0
需要从SQLite官网下载源代码:
sqlite-amalgamation-*.zip
sqlite-dll-win32-x86-*.zip
sqlite-src-*.zip
sqlite-preprocessed-*.zip
1、 编译成Win32下的应用程序(*.exe),用于命令行模式下的调试
(1)启动VC++6.0,创建一个Win32 Console Application空的工程,工程名为“SQlite”;
(2)将sqlite-amalgamation-*.zip 解压后的shell.c、sqlite3.c、sqlite3.h、sqlite3ext.h添加到工程中,直接编译即可生成sqlite.exe,可以在命令提示符下进行测试。
编译时,出现以下错误:unresolved external symbol __beginthreadex
unresolved external symbol __endthreadex
这是在使用MFC的类时出现连接错误。
解决方法:
1.工程右键——>“Project”菜单——〉“Setting”菜单项——〉General选项卡,在Microsoft Fountion Classes:中选择:Use MFC in Static Library。
2.再在C/C++选项卡中的在Category中选择Code Generation,再在Use run-time library中选择Debug Multithreaded(若在Win32 Debug环境下)或者multithreaded。
其中:
Single-Threaded单线程静态链接库(release版本)
Multithreaded多线程静态链接库(release版本)
multithreaded DLL多线程动态链接库(release版本)
Debug Single-Threaded单线程静态链接库(debug版本)
Debug Multithreaded多线程静态链接库(debug版本)
Debug Multithreaded DLL多线程动态链接库(debug版本)
2、编译生成Win32平台下的动态链接库(*.dll)。
(1)启动VC++6.0,创建一个Win32 Dynamic_Link Library,选择一个空的DLL工程,工程名为“SQLite_Win32_DLL”;
(2)将sqlite-amalgamation-*.zip解压后的sqlite3.c、sqlite3.h、sqlite3ext.h以及sqlite-dll-win32-x86-*.zip解压后的sqlite3.def模块定义文件一起添加到工程中;
(3)【Project】->【Settings…】->【C/C++】->【Category】->【General】->【Preprocessor definitions】
新增编译选项:SQLITE_ENABLE_COLUMN_METADATA,编译通过即可生成dll。
但此时只生成了sqlite_win32_dll.dll文件,没有生成对应的引入库(sqlite_win32_dll.lib)文件。
具体方法是如下:
修改sqlite3.c文件中的SQLITE_API宏定义,将“# define SQLITE_API”修改成“# define SQLITE_API __declspec(dllexport)”。
或者直接把sqlite3.def添加在Linker--->Input--->Module Definition File中。
再重新编译即可生成sqlite_win32_dll.dll和sqlite_win32_dll.lib。
SQLite应用
使用命令行工具我们可以完成大多数常用的SQLite操作,就像sqlplus之于Oracle。下表介绍了该工具的内置命令:
命令名 | 命令说明 |
.help | 列出所有内置命令。 |
.backup DBNAME FILE | 备份指定的数据库到指定的文件,缺省为当前连接的main数据库。 |
.databases | 列出当前连接中所有attached数据库名和文件名。 |
.dump TABLENAME ... | 以SQL文本的格式DUMP当前连接的main数据库,如果指定了表名,则只是DUMP和表名匹配的数据表。参数TABLENAME支持LIKE表达式支持的通配符。 |
.echo ON|OFF | 打开或关闭显示输出。 |
.exit | 退出当前程序。 |
.explain ON|OFF | 打开或关闭当前连接的SELECT输出到Human Readable形式。 |
.header(s) ON|OFF | 在显示SELECT结果时,是否显示列的标题。 |
.import FILE TABLE | 导入指定文件的数据到指定表。 |
.indices TABLENAME | 显示所有索引的名字,如果指定表名,则仅仅显示匹配该表名的数据表的索引,参数TABLENAME支持LIKE表达式支持的通配符。 |
.log FILE|off | 打开或关闭日志功能,FILE可以为标准输出stdout,或标准错误输出stderr。 |
.mode MODE TABLENAME | 设置输出模式,这里最为常用的模式是column模式,使SELECT输出列左对齐显示。 |
.nullvalue STRING | 使用指定的字符串代替NULL值的显示。 |
.output FILENAME | 将当前命令的所有输出重定向到指定的文件。 |
.output stdout | 将当前命令的所有输出重定向到标准输出(屏幕)。 |
.quit | 退出当前程序。 |
.read FILENAME | 执行指定文件内的SQL语句。 |
.restore DBNAME FILE | 从指定的文件还原数据库,缺省为main数据库,此时也可以指定其它数据库名,被指定的数据库成为当前连接的attached数据库。 |
.schema TABLENAME | 显示数据表的创建语句,如果指定表名,则仅仅显示匹配该表名的数据表创建语句,参数TABLENAME支持LIKE表达式支持的通配符。 |
.separator STRING | 改变输出模式和.import的字段间分隔符。 |
.show | 显示各种设置的当前值。 |
.tables TABLENAME | 列出当前连接中main数据库的所有表名,如果指定表名,则仅仅显示匹配该表名的数据表名称,参数TABLENAME支持LIKE表达式支持的通配符。 |
.width NUM1 NUM2 ... | 在MODE为column时,设置各个字段的宽度,注意:该命令的参数顺序表示字段输出的顺序。 |
打开cmd,输入sqlite3
① 创建SQLite 数据库
现在你已经安装了 SQLite 数据库,接下来我们创建首个数据库。在命令行窗口中输入如下命令来创建一个名为 test.db 的数据库。
- sqlite3 test.db
② 创建表
- sqlite> createtable mytable(id integerprimarykey, value text);
- 2 columns were created.
该表包含一个名为 id 的主键字段和一个名为 value 的文本字段。
注意: 最少必须为新建的数据库创建一个表或者视图,这么才能将数据库保存到磁盘中,否则数据库不会被创建。
接下来往表里中写入一些数据。
③ 插入数据
- sqlite> insertinto mytable(id, value) values(1, 'Micheal');
- sqlite> insertinto mytable(id, value) values(2, 'Jenny');
- sqlite> insertinto mytable(value) values('Francis');
- sqlite> insertinto mytable(value) values('Kerk');
④ 查询数据
- sqlite> select * from test;
- 1|Micheal
- 2|Jenny
- 3|Francis
- 4|Kerk
⑤ 设置格式化查询结果
- sqlite> .mode column;
- sqlite> .header on;
- sqlite> select * from test;
- id value
- ----------- -------------
- 1 Micheal
- 2 Jenny
- 3 Francis
- 4 Kerk
.mode column 将设置为列显示模式,.header 将显示列名。
⑥ 修改表结构,增加列
- sqlite> alter table mytable add column email text not null '' collate nocase;;
⑦ 创建视图
- sqlite> create view nameview as select * from mytable;
⑧ 创建索引
- sqlite> create index test_idx on mytable(value);
⑨ 其他 SQLite 命令
显示表结构:
- sqlite> .schema [table]
获取所有表和视图:
- sqlite > .tables
获取指定表的索引列表:
- sqlite > .indices [table ]
导出数据库到 SQL 文件:
- sqlite > .output [filename ]
- sqlite > .dump
- sqlite > .output stdout
从 SQL 文件导入数据库:
- sqlite > .read [filename ]
格式化输出数据到 CSV 格式:
- sqlite >.output [filename.csv ]
- sqlite >.separator ,
- sqlite > select * from test;
- sqlite >.output stdout
从 CSV 文件导入数据到表中:
- sqlite >createtable newtable ( id integerprimarykey, value text );
- sqlite >.import [filename.csv ] newtable
备份数据库:
- /* usage: sqlite3 [database] .dump > [filename] */
- sqlite3 mytable.db .dump > backup.sql
恢复数据库:
- /* usage: sqlite3 [database ] < [filename ] */
- sqlite3 mytable.db < backup.sql
多线程环境中使用SQLite
SQLite支持三种不同的线程模式:
* 单线程。在这种模式下所有的互斥锁都被禁用,在多个线程中同时使用SQLite时是不安全的。
* 多线程。在这种模式下,只要没有单个数据库连接被同时用在多个线程中的情况,SQLite就可以在多线程环境中安全地使用。
* 串行化。在这种模式中,SQLite可以无限制地在多线程环境中安全地使用。
线程模式可以在编译时(把SQLite源代码编译成库时)、启动时(使用SQLite的应用程序初始化时)或运行时(一个新的SQLite数据库连接创建时)指定。一般来说,运行时参数会覆盖掉启动时参数,启动时参数会覆盖掉编译时参数,但是单线程模式一旦被指定后,就不能被覆盖。默认的模式是串行模式。
(1)编译时的线程模式选项
通过SQLITE_THREADSAFE编译时参数来选择线程模式。如果没有指定SQLITE_THREADSAFE参数,则使用串行化模式。也可以显式地使用-DSQLITE_THREADSAFE=1来指定串行化模式。-DSQLITE_THREADSAFE=0表示单线程模式,-DSQLITE_THREADSAFE=2表示多线程模式。
sqlite3_threadsafe()接口的返回值由编译时线程模式选项来确定。如果编译时指定单线程模式,则sqlite3_threadsafe()返回false。如果指定多线程模式或串行化模式,则sqlite3_threadsafe()返回true。sqlite3_threadsafe()不能区分多线程模式和串行化模式,也不能报告启动时或运行时的模式更改。
如果编译时指定单线程模式,则编译库时关键的互斥逻辑会被忽略,因此不可能在启动时或运行不可能再激活多线程或串行化模式。
(2)启动时的线程模式选项
如果编译时没有指定单线程模式,则在使用sqlite3_config()接口进行初始化时可以改变线程模式。SQLITE_CONFIG_SINGLETHREAD谓词把SQLite设置成单线程模式,SQLITE_CONFIG_MULTITHREAD设置多线程模式,SQLITE_CONFIG_SERIALIZED设置串行化模式。
(3)运行时的线程模式选项
如果编译时或启动时没有指定单线程模式,则单个数据连接可以被创建为多线程或串行化模式,不可能将单个数据库连接降级为单线程模式。如果编译时或启动时指定单线程模式,则不可能将单个数据库连接升级为多线程或串行化模式。
单个数据库连接的线程模式由sqlite3_open_v2()的第三个参数给定的标志来确定。SQLITE_OPEN_NOMUTEX标志表示数据库连接为多线程模式,SQLITE_OPEN_FULLMUTEX表示该连接为串行化模式。如果没有指定标志,或者使用sqlite3_open(), sqlite3_open16(),而不是sqlite3_open_v2(),则使用编译时或启动时指定的线程模式。