|
对于大多数应用程序来说,构建SQLite的推荐方法是使用混合代码文件——sqlite3.c,以及相对应的头文件sqlite3.h。sqlite3.c源码文件可以无需修改任何编译选项在Unix、Windows、OS/2、Mac OS X等系统上编译。多数应用程序只需要简单的将sqlite3.c文件包含到应用程序的其它C代码文件中,然后一起编译,然后就可以得到一个配置良好、可以使用的SQLite了。
For most applications, the recommended method for building
SQLite is to use the amalgamation code
file, sqlite3.c, and its corresponding header file
sqlite3.h. The sqlite3.c code file should compile and
run on any Unix, Windows, OS/2, or Mac OS X system without any changes
or special compiler options. Most applications can simply include
the sqlite3.c file together with the other C code files that make
up the application, compile them all together, and have working
and well configured version of SQLite.
大多数的应用程序无需使用任何特别的编译期配置,SQLite默认的配置就可以使其良好的工作了。大多数开发者完全可以彻底抛弃这篇文档,只要简单的使用混合代码构建SQLite就可以了,这不需要任何专业的知识或者其它任何专门的操作。
Most applications work great with SQLite in its default configuration and with no special compile-time configuration. Most developers should be able to completely ignore this document and simply build SQLite from the amalgamation without any special knowledge and without taking any special actions.
但是,高度特化和校调的应用程序可能会需要将SQLite一些内置的系统接口实现进行替换,以便更加符合应用的需求。在SQLite的设计中,在面对各种特定的项目的时候非常容易在编译期从新配置。SQLite的编译期配置包含下列这些内容:
However, highly tuned and specialized
applications may want or need to replace some of
SQLite's built-in system interfaces with alternative implementations
more suitable for the needs of the application. SQLite is designed
to be easily reconfigured at compile-time to meet the specific
needs of individual projects. Among the compile-time configuration
options for SQLite are these:
将内置的互斥锁子系统替换为其它实现。
Replace the built-in mutex subsystem with an alternative
implementation.
在单线程应用程序中,彻底禁用所有的互斥锁。
Completely disable all mutexing for use in single-threaded
applications.
将内置的内存分配子系统替换为标准库中的malloc()以外的实现。
Reconfigure the memory allocation subsystem to use a memory
allocator other the malloc() implementation from the standard
library.
重组内存分配子系统,以便不再调用malloc(),而是使用启动时分配给SQLite的固定大小的内存缓冲区来满足所有的内存请求。
Realign the memory allocation subsystem so that it never calls
malloc() at all but instead satisfies all memory requests using
a fixed-size memory buffer assigned to SQLite at startup.
替换文件系统的接口。也就是说,重载SQLite提供的所有系统调用,以便使用一套完全不同的系统调用来访问磁盘。
Replace the interface to the file system with an alternative
design. In other words, override all of the system calls that
SQLite makes in order to talk to the disk with a completely different
set of system calls.
重写其它操作系统接口,例如获取系统时间的调用。
Override other operating system interfaces such as calls to obtain
Zulu or local time.
通俗来讲,在SQLite中包含三个独立的子系统,它们都可以在编译期进行修改或重载。互斥锁子系统是用来在多线程访问共享资源时进行访问串行化的。内存分配子系统是用来为数据库缓存和SQLite对象分配所需的内存的。最后,虚拟文件系统是用来在SQLite和底层的操作系统的特定文件系统之间提供一套可移植的接口。我们将这三个子系统称作SQLite的“接口”子系统。
Generally speaking, there are three separate subsystems within
SQLite that can be modified or overridden at compile-time. The
mutex subsystem is used to serialize access to SQLite resources that
are shared among threads. The memory allocation subsystem is used
to allocate memory required by SQLite objects and for the database
cache. Finally, the Virtual File System subsystem is
used to provide a portable interface between SQLite and the underlying
operating system and especially the file system. We call these three
subsystems the "interface" subsystems of SQLite.
我们再次强调,多数系统使用SQLite接口子系统的内置默认实现就可以很好的工作了。我们鼓励开发者使用内置的默认实现,而无需在构建SQLite时使用任何编译期的选项或者参数。
但是,一些高度特化的应用程序可能可以从替换或者修改多个SQLite内置的接口子系统中获益。或者,如果使用SQLite的操作系统不是Unix(Linux、Mac OS X)、Windows(Win32、WinCE)或OS/2,那么内置的接口子系统都将无法工作,这时就需要应用程序来提供适用于目标平台的子系统实现了。
We emphasis that most applications are well-served by the
built-in default implementations of the SQLite interface subsystems.
Developers are encouraged to use the
default built-in implementations whenever possible
and to build SQLite without any special compile-time options or parameters.
However, some highly specialized applications may benefit from
substituting or modifying one or more of these built-in SQLite
interface subsystems.
Or, if SQLite is used on an operating system other than
Unix (Linux or Mac OS X), Windows (Win32 or WinCE), or OS/2 then none
of the interface subsystems that come built into SQLite will work
and the application will need to provide alternative implementations
suitable for the target platform.
在多线程环境中,SQLite使用互斥锁来对共享资源的访问进行串行化。只有需要在多线程访问SQLite的应用程序才需要互斥锁子系统。对于单线程的应用或只会在单线程中调用SQLite的应用来说,完全可以使用下面选项重新编译SQLite来彻底禁用互斥体子系统:
In a multithreaded environment, SQLite uses mutexes to serialize
access to shared resources.
The mutex subsystem is only required for applications that access
SQLite from multiple threads. For single-threaded applications, or
applications which only call SQLite from a single thread, the mutex
subsystem can be completely disabled by recompiling with the following
option:
-DSQLITE_THREADSAFE=0
互斥锁的开销很小,但并不是没有,所以当完全禁用了互斥锁后性能会得到提升。最终的封装库大小也会变的小一些。当这些是有意义的情况下,推荐在编译期禁用互斥锁。
Mutexes are cheap but they are not free, so performance will be better
when mutexes are completely disabled. The resulting library footprint
will also be a little smaller. Disabling the mutexes at compile-time
is a recommended optimization for applications where it makes sense.
当把SQLite作为共享库使用时,应用程序可以使用sqlite3_threadsafe() API来测试看互斥锁是否禁用了。所有在运行时连接SQLite并且会在多线程环境下使用SQLite的应用程序都应该检查一下这个API,以确保不会意外连入一个禁用了互斥锁的SQLite库版本。当然,单线程应用不管SQLite是否配置为线程安全都可以正确的运行,不过如果使用禁用互斥锁的SQLite版本能够运行的稍微快一些。
When using SQLite as a shared library, an application can test to see
whether or not mutexes have been disabled using the
sqlite3_threadsafe() API. Applications that link against SQLite at
run-time and use SQLite from multiple threads should probably check this
API to make sure they did not accidentally get linked against a version of
the SQLite library that has its mutexes disabled. Single-threaded
applications will, of course, work correctly regardless of whether or
not SQLite is configured to be threadsafe, though they will be a little
bit faster when using versions of SQLite with mutexes disabled.
SQLite互斥锁也可以在运行时使用sqlite3_config()接口来禁用。应用程序可以执行下面接口来完全禁用所有互斥锁:
SQLite mutexes can also be disabled at run-time using the
sqlite3_config() interface. To completely disable all mutexing,
the application can invoke:
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
在运行时禁用互斥锁并没有编译期禁用那么高效,这是因为SQLite在每个需要互斥锁的地方还必须做一个布尔值的判断来确认互斥锁是否禁用了。不过运行时禁用互斥锁依然可以带来性能提升。
Disabling mutexes at run-time is not as effective as disabling them
at compile-time since SQLite still must do a test of a boolean variable
to see if mutexes are enabled or disabled at each point where a mutex
might be required. But there is still a performance advantage for
disabling mutexes at run-time.
对于多线程应用程序,需要关心它们是如何管理线程的。SQLite支持一个可选的运行时配置,是位于不使用任何互斥锁和默认的对所有内容使用互斥锁的中间状态。这个“中间态”互斥锁可以使用下面的方式来建立:
For multi-threaded applications that are careful about how they
manage threads, SQLite supports an alternative run-time configuration
that is half way between not using any mutexes and the default situation
of mutexing everything in sight. This in-the-middle mutex alignment can
be established as follows:
sqlite3_config(SQLITE_CONFIG_MULTITHREAD); sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0);
这里有两个独立的配置改动,二者可以一起使用也可以分开使用。SQLITE_CONFIG_MULTITHREAD设置可以禁用对数据库连接对象和预编译语句对象串行化访问所需的互斥锁。使用这个设置,应用程序就可以自由的在多线程环境下使用SQLite了,但是必须要确保不会出现两个以上线程访问同一个数据库连接,或者是同时访问同一个数据库连接相关联的多个预编译语句。两个线程可以同时访问SQLite,但是必须使用两个独立的数据库连接。
第二个设置SQLITE_CONFIG_MEMSTATUS可以禁用SQLite中统计所有内存分配请求的总内存数量的机制。这个设置可以取消每次sqlite3_malloc() 和 sqlite3_free()调用所需的互斥锁,这可以减少大量的互斥锁操作。但是禁用内存统计机制的结果是sqlite3_memory_used()、sqlite3_memory_highwater()和sqlite3_soft_heap_limit64()接口都无法使用了。
There are two separate configuration changes here which can
be used either togethr or separately. The
SQLITE_CONFIG_MULTITHREAD setting disables the mutexes that
serialize access to database connection objects and
prepared statement objects. With this setting, the application
is free to use SQLite from multiple threads, but it must make sure
than no two threads try to access the same database connection
or any prepared statements associated with the same
database connection at the same time. Two threads can use SQLite
at the same time, but they must use separate database connections.
The second SQLITE_CONFIG_MEMSTATUS setting disables the mechanism
in SQLite that tracks the total size of all outstanding memory
allocation requests. This omits the need to mutex each call
to sqlite3_malloc() and sqlite3_free(), which saves a huge
number of mutex operations. But a consequence of disabling the
memory statistics mechanism is that the
sqlite3_memory_used(), sqlite3_memory_highwater(), and
sqlite3_soft_heap_limit64() interfaces cease to work.
SQLite在Unix上使用pthread实现的互斥锁,并且SQLite中需要递归锁。大多数现代的pthread实现都支持递归锁,但并不是全部。对于不支持递归锁的系统来说,推荐应用程序只在单线程模式下运行。如果这不可能,SQLite提供了一个以pthread中的标准“快速”互斥锁为基础实现的递归锁。只要pthread_equal()是原子的,并且处理器有相干数据缓存,那么这个实现就可以正确的工作。这个可选的递归锁实现可以使用下面的编译器命令行开关来启用:
SQLite uses pthreads for its mutex implementation on Unix and
SQLite requires a recursive mutex. Most modern pthread implementations
support recursive mutexes, but not all do. For systems that do not
support recursive mutexes, it is recommended that applications operate
in single-threaded mode only. If this is not possible, SQLite provides
an alternative recursive mutex implementation built on top of the
standard "fast" mutexes of pthreads. This alternative
implementation should work correctly as long as pthread_equal() is
atomic and the processor has a coherent data cache. The alternative
recursive mutex implementation is enabled by the following
compiler command-line switch:
-DSQLITE_HOMEGROWN_RECURSIVE_MUTEX=1
当把SQLite移植到新的操作系统上时,通常需要使用一个新操作系统互斥锁原语构建的互斥锁子系统来完全替换内置的互斥锁子系统。这可以通过使用下面的选项编译SQLite来实现:
When porting SQLite to a new operating system, it is usually necessary
to completely replace the built-in mutex subsystem with an alternative
built around the mutex primitives of the new operating system. This
is accomplished by compiling SQLite with the following option:
-DSQLITE_MUTEX_APPDEF=1
当使用 SQLITE_MUTEX_APPDEF=1选项编译SQLite时,会完全忽略内置的互斥锁原始函数实现。但是SQLite库在需要的时候依然会调用这些函数,所以应用程序必须自己实现这些互斥锁原始函数,并将其与SQLite链接到一起。
When SQLite is compiled with the SQLITE_MUTEX_APPDEF=1 option, it
completely omits the implementation of its
mutex primitive functions. But the SQLite
library still attempts to call these functions where necessary, so the
application must itself implement the
mutex primitive functions and link them together
with SQLite.
默认情况,SQLite从标准库中的malloc()/free()实现来获取对象和缓存所需的内存。还有一个还处于实验状态的内存分配器,这个分配器可以使用在应用启动时分配给SQLite的一块儿固定大小的内存缓冲区来满足所有的内存分配请求。更多关于实验性内存分配器的内容将会在本文未来的版本中提供。
By default, SQLite obtains the memory it needs for objects and
cache from the malloc()/free() implementation of the standard library.
There is also on-going work with experimental memory allocators that
satisfy all memory requests from a single fixed memory buffer handed
to SQLite at application start. Additional information on these
experimental memory allocators will be provided in a future revision
of this document.
SQLite能够支持应用程序在运行时指定一个可选的内存分配器。首先将实现内存分配的函数的指针填入到一个sqlite3_mem_methods对象的实例中,然后将这个对象使用sqlite3_config()接口注册到系统中。例如:
SQLite supports the ability of an application to specify an alternative
memory allocator at run-time by filling in an instance of the
sqlite3_mem_methods object with pointers to the routines of the
alternative implementation then registering the new alternative
implementation using the sqlite3_config() interface.
For example:
sqlite3_config(SQLITE_CONFIG_MALLOC, &my_malloc_implementation);
SQLite会将sqlite3_mem_methods的内容复制一份,所以在sqlite3_config()调用返回后就可以修改这个对象的内容了。
SQLite makes a copy of the content of the sqlite3_mem_methods object
so the object can be modified after the sqlite3_config() call returns.
从 3.5.0 版开始,SQLite支持了一个叫做虚拟文件系统 或 "VFS"的接口。这个对象的名字取的有些不太恰当,因为这实际上是整个底层操作系统的接口,而不仅仅是文件系统。
Since version 3.5.0, SQLite has supported an interface called the
virtual file system or "VFS".
This object is somewhat misnamed since it
is really an interface to the whole underlying operating system, not
just the filesystem.
VFS接口的一个有趣的特征是,SQLite可以同时支持多个VFS。当每个数据库连接使用sqlite3_open_v2()接口第一次打开时,需要选择一个VFS供其使用。但是如果一个进程包含多个数据库连接,那么每个连接可以选择不同的VFS。可以再运行时通过sqlite3_vfs_register()接口来添加VFS。
One of the interesting features
of the VFS interface is that SQLite can support multiple VFSes at the
same time. Each database connection has to choose a single VFS for its
use when the connection is first opened using sqlite3_open_v2().
But if a process contains multiple database connections each can choose
a different VFS. VFSes can be added at run-time using the
sqlite3_vfs_register() interface.
在Unix、Windows和OS/2上构建的SQLite都默认包含了适合目标平台的VFS。在其它平台上构建的SQLite则默认不包含VFS,不过应用程序可以再运行时注册一个或多个VFS。
The default builds for SQLite on Unix, Windows, and OS/2 include
a VFS appropriate for the target platform. SQLite builds for other
operating systems do not contain a VFS by default, but the application
can register one or more at run-time.
为了将SQLite移植到新的操作系统中(一个默认不支持的系统),应用程序需要提供:
In order to port SQLite to a new operating system - an operating
system not supported by default - the application
must provide...
所有的这些内容都可以在一个辅助的C源码文件中提供,并将其与已有的“sqlite3.c”源码文件链接在一起来生成一个在目标操作系统上可以运行的SQLite版本。除了互斥锁和内存分配子系统以及新的VFS以外,这个辅助C源码文件还需要包含下面两个接口的实现:
All of these things can be provided in a single auxiliary C code file
and then linked with the stock "sqlite3.c" code file to generate a working
SQLite build for the target operating system. In addition to the
alternative mutex and memory allocation subsystems and the new VFS,
the auxiliary C code file should contain implementations for the
following two routines:
“sqlite3.c”源文件中包含了默认的VFS实现,以及适合Unix、Windows和OS/2的sqlite3_initialize() 与 sqlite3_shutdown()函数。要想在编译sqlite3.c时防止加载这些默认的组件,就需要添加一个编译期选项:
The "sqlite3.c" code file contains default implementations of a VFS
and of the sqlite3_initialize() and sqlite3_shutdown() functions that
are appropriate for Unix, Windows, and OS/2.
To prevent one of these default components from being loaded when sqlite3.c
is compiled, it is necessary to add the following compile-time
option:
-DSQLITE_OS_OTHER=1
SQLite内核会在提早调用sqlite3_initialize()。辅助C源文件可以包含sqlite3_initialize()的实现,这个函数可以注册合适的VFS,也可以初始化互斥锁系统(如果需要互斥锁)或者内存分配子系统所需的初始化工作。
SQLite核心永远不会调用sqlite3_shutdown(),但是这是官方SQLite API的一部分,必须在使用-DSQLITE_OS_OTHER=1编译的时候提供。所以辅助C源文件需要提供这个函数。
The SQLite core will call sqlite3_initialize() early. The auxiliary
C code file can contain an implementation of sqlite3_initialize() that
registers an appropriate VFS and also perhaps initializes an alternative
mutex system (if mutexes are required) or does any memory allocation
subsystem initialization that is required.
The SQLite core never calls sqlite3_shutdown() but it is part of the
official SQLite API and is not otherwise provided when compiled with
-DSQLITE_OS_OTHER=1, so the auxiliary C code file should probably provide
it for completeness.