首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Custom Builds Of SQLite

1.0简介

对于大多数应用程序,建议SQLite的建议方法是使用合并代码文件sqlite3.c及其相应的头文件sqlite3.h。sqlite3.c代码文件应该可以在任何unix,Windows系统上编译和运行,而不需要任何更改或特殊的编译器选项。大多数应用程序可以简单地将sqlite3.c文件与组成应用程序的其他C代码文件一起包含,将它们一起编译,并且具有工作和良好配置的SQLite版本。

大多数应用程序在SQLite默认配置下工作良好,并且没有特殊的编译时配置。大多数开发人员应该能够完全忽略这个文档,只需从 合并中 毫不费力地构建SQLite ,而不需要采取任何特殊的行动。

然而,经过高度调优和专门化的应用程序可能需要或需要用一些更适合应用程序需求的替代实现来替换SQLite的一些内置系统接口。SQLite旨在在编译时轻松进行重新配置,以满足各个项目的特定需求。SQLite的编译时配置选项包括:

  • 用另一种实现替换内置互斥子系统。
  • 完全禁用所有在单线程应用程序中使用的互斥。
  • 重新配置内存分配子系统以使用来自标准库的malloc()实现以外的内存分配器。
  • 重新调整内存分配子系统,以便它根本不调用malloc(),而是使用在启动时分配给SQLite的固定大小内存缓冲区来满足所有内存请求。
  • 使用替代设计将接口替换为文件系统。换句话说,覆盖SQLite为了用完全不同的系统调用与磁盘进行通信所进行的所有系统调用。
  • 覆盖其他操作系统接口,例如调用以获取祖鲁语或当地时间。

一般来说,SQLite中有三个独立的子系统,可以在编译时修改或重写。互斥子系统用于序列化对线程间共享的SQLite资源的访问。内存分配子系统用于分配SQLite对象和数据库缓存所需的内存。最后,虚拟文件​​系统子系统用于在SQLite和底层操作系统,特别是文件系统之间提供一个可移植的接口。我们称这三个子系统为SQLite的“接口”子系统。

我们强调大多数应用程序都由SQLite接口子系统的内置默认实现提供良好的服务。鼓励开发人员尽可能使用默认的内置实现,并且无需任何特殊的编译时选项或参数即可构建SQLite。但是,一些高度专业化的应用程序可能会从替换或修改一个或多个内置SQLite接口子系统中受益。或者,如果在Unix(Linux或Mac OS X),Windows(Win32或WinCE)或OS / 2以外的操作系统上使用SQLite,则SQLite中内置的任何接口子系统都不会工作,而且应用程序需要以提供适合于目标平台的替代实现。

2.0配置或更换Mutex子系统

在多线程环境中,SQLite使用互斥锁来序列化对共享资源的访问。互斥子系统仅适用于从多个线程访问SQLite的应用程序。对于单线程应用程序或仅从单个线程调用SQLite的应用程序,通过使用以下选项重新编译,可以完全禁用互斥子系统:

代码语言:javascript
复制
-DSQLITE_THREADSAFE = 0

互斥体很便宜,但它们不是免费的,所以当互斥体完全禁用时性能会更好。由此产生的库足迹也会稍小一些。在编译时禁用这些互斥锁是对它有意义的应用程序的推荐优化。

将SQLite用作共享库时,应用程序可以使用sqlite3_threadsafe()API测试是否禁用互斥锁。在运行时与SQLite链接并从多个线程使用SQLite的应用程序应该检查此API,以确保它们不会意外链接到禁用了互斥锁的SQLite库的版本。当然,无论SQLite是否配置为线程安全,单线程应用程序都能正常工作,但在使用禁用互斥锁的SQLite版本时,它会快一点。

SQLite互斥锁也可以在运行时使用sqlite3_config()接口禁用。为了完全禁用所有的静音,应用程序可以调用:

代码语言:javascript
复制
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);

在运行时禁用互斥锁并不像在编译时禁用互斥锁一样有效,因为SQLite仍然必须对布尔变量进行测试,以查看互斥锁可能需要的每个点的启用还是禁用。但是在运行时禁用互斥锁仍然具有性能优势。

对于注意管理线程的多线程应用程序,SQLite支持另一种运行时配置,这种配置是不使用任何互斥锁和忽略所有内容的默认情况之间的一半。这个中间互斥对齐可以如下建立:

代码语言:javascript
复制
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()接口停止工作。

SQLite在Unix上使用pthreads来实现它的互斥体实现,SQLite需要递归互斥体。大多数现代pthread实现都支持递归互斥锁,但并非所有的都可以。对于不支持递归互斥锁的系统,建议应用程序仅以单线程模式运行。如果这是不可能的,SQLite提供了一个在pthread的标准“快速”互斥体之上构建的替代递归互斥体实现。只要pthread_equal()是原子且处理器具有一致的数据高速缓存,此替代实现应该可以正常工作。以下编译器命令行开关启用了备用递归互斥体实现:

代码语言:javascript
复制
-DSQLITE_HOMEGROWN_RECURSIVE_MUTEX=1

将SQLite移植到新的操作系统时,通常需要用内置的互斥体子系统的互斥体原语替代内置的互斥体子系统。这是通过使用以下选项编译SQLite来完成的:

代码语言:javascript
复制
-DSQLITE_MUTEX_APPDEF=1

当使用SQLITE_MUTEX_APPDEF = 1选项编译SQLite时,它完全省略了其互斥体原语函数的实现。但是SQLite库仍然会在必要时尝试调用这些函数,所以应用程序必须自己实现互斥体原语函数并将它们与SQLite链接在一起。

3.0配置或更换内存分配子系统

默认情况下,SQLite从标准库的malloc()/ free()实现中获取对象和缓存所需的内存。还有一些正在进行的实验性内存分配器,它们可以满足从应用程序启动时交给SQLite的单个固定内存缓冲区的所有内存请求。有关这些实验性内存分配器的更多信息将在本文档的未来版本中提供。

SQLite支持应用程序在运行时指定替代内存分配器的能力,方法是使用指向替代实现的例程的指针填充sqlite3_mem_methods对象的实例,然后使用sqlite3_config()接口注册新的替代实现。例如:

代码语言:javascript
复制
sqlite3_config(SQLITE_CONFIG_MALLOC, &my_malloc_implementation);

SQLite创建sqlite3_mem_methods对象的内容的副本,以便在sqlite3_config()调用返回后修改对象。

4.0添加新的虚拟文件系统

版本3.5.0(2007-09-04)开始,SQLite支持称为虚拟文件系统或“VFS”的接口。这个对象有些误称,因为它实际上是整个底层操作系统的接口,而不仅仅是文件系统。

VFS接口的一个有趣功能是SQLite可以同时支持多个VFS。当连接首次使用sqlite3_open_v2()打开时,每个数据库连接都必须选择一个VFS供其使用。但是如果一个进程包含多个数据库连接,每个连接可以选择不同的VFS。可以使用sqlite3_vfs_register()接口在运行时添加VFSes。

Unix,Windows和OS / 2上SQLite的默认构建包括适用于目标平台的VFS。SQLite为其他操作系统构建的默认情况下不包含VFS,但应用程序可以在运行时注册一个或多个VFS。

5.0将SQLite移植到新的操作系统

为了将SQLite移植到新操作系统 - 默认不支持的操作系统 - 应用程序必须提供...

  • 一个工作互斥子系统(但只有在它是多线程的时候),
  • 一个工作内存分配子系统(假设它的标准库中没有malloc()),和
  • 一个可行的VFS实施。

所有这些都可以在单个辅助C代码文件中提供,然后与库存“sqlite3.c”代码文件链接,以生成适用于目标操作系统的可用SQLite版本。除了替代互斥和内存分配子系统以及新的VFS之外,辅助C代码文件还应包含以下两个例程的实现:

  • sqlite3_os_init()
  • sqlite3_os_end()

“sqlite3.c”代码文件包含适用于Unix,Windows和OS / 2的VFS和sqlite3_initialize()和sqlite3_shutdown()函数的默认实现。为了防止编译sqlite3.c时加载这些默认组件之一,需要添加以下编译时选项:

代码语言:javascript
复制
-DSQLITE_OS_OTHER=1

SQLite核心将尽早调用sqlite3_initialize()。辅助C代码文件可以包含一个sqlite3_initialize()实现,该实现注册一个适当的VFS,并且还可能初始化一个替代互斥体系统(如果需要互斥体)或执行任何所需的内存分配子体系初始化。SQLite核心永远不会调用sqlite3_shutdown(),但它是官方SQLite API的一部分,并且在使用-DSQLITE_OS_OTHER = 1进行编译时不另外提供,所以辅助C代码文件可能应该提供完整性。

代码语言:javascript
复制
 SQLite在公共领域。

扫码关注腾讯云开发者

领取腾讯云代金券