Пользовательские сборки SQLite
или
Перенос 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 использует для взаимодействия с диском, полностью другим набором системных вызовов.
Переопределить другие интерфейсы операционной системы, например вызовы для получения времени UTC или местного времени.
В целом, в SQLite есть три отдельные подсистемы, которые можно изменить или переопределить во время компиляции. Подсистема мьютексов используется для сериализации доступа к ресурсам SQLite, совместно используемым несколькими потоками. Подсистема выделения памяти используется для выделения памяти, необходимой объектам SQLite и кэшу базы данных. Наконец, подсистема виртуальной файловой системы используется для обеспечения переносимого интерфейса между SQLite и базовой операционной системой, в особенности файловой системой. Мы называем эти три подсистемы подсистемами «интерфейса» SQLite.
Подчеркнём, что встроенные реализации подсистем интерфейса SQLite по умолчанию хорошо подходят для большинства приложений. Разработчикам рекомендуется по возможности использовать встроенные реализации по умолчанию и собирать SQLite без специальных параметров или аргументов времени компиляции. Однако некоторым узкоспециализированным приложениям может быть полезно заменить или изменить одну или несколько встроенных подсистем интерфейса SQLite. Кроме того, если SQLite используется в операционной системе, отличной от Unix (Linux или Mac OS X), Windows (Win32 или WinCE) либо OS/2, ни одна из встроенных в SQLite подсистем интерфейса не будет работать, и приложению потребуется предоставить альтернативные реализации, подходящие для целевой платформы.
2.0 Настройка или замена подсистемы мьютексов
В многопоточной среде SQLite использует мьютексы для сериализации доступа к совместно используемым ресурсам. Подсистема мьютексов необходима только приложениям, которые обращаются к SQLite из нескольких потоков. В однопоточных приложениях или приложениях, которые вызывают SQLite только из одного потока, подсистему мьютексов можно полностью отключить, выполнив повторную компиляцию со следующим параметром:
-DSQLITE_THREADSAFE=0
Мьютексы требуют дополнительных ресурсов, пусть и незначительных, поэтому при их полном отключении производительность будет выше. Размер получившейся библиотеки также будет немного меньше. Отключение мьютексов во время компиляции рекомендуется в тех приложениях, где это целесообразно.
При использовании SQLite в качестве разделяемой библиотеки приложение может проверить, отключены ли мьютексы, с помощью API sqlite3_threadsafe(). Приложения, которые подключают SQLite во время выполнения и используют её из нескольких потоков, вероятно, должны проверять этот API, чтобы убедиться, что случайно не подключили версию библиотеки SQLite с отключёнными мьютексами. Однопоточные приложения, разумеется, будут работать правильно независимо от того, настроена ли SQLite для поддержки потоков, хотя с версиями SQLite, в которых мьютексы отключены, они будут работать немного быстрее.
Мьютексы SQLite также можно отключить во время выполнения с помощью интерфейса sqlite3_config(). Чтобы полностью отключить все мьютексы, приложение может вызвать:
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
Отключение мьютексов во время выполнения не так эффективно, как их отключение во время компиляции, поскольку SQLite всё равно должна проверять значение логической переменной, чтобы определить, включены мьютексы или отключены, каждый раз, когда мьютекс может потребоваться. Тем не менее отключение мьютексов во время выполнения всё равно повышает производительность.
Для многопоточных приложений, в которых потоки используются аккуратно, SQLite поддерживает альтернативную конфигурацию времени выполнения, промежуточную между полным отказом от мьютексов и вариантом по умолчанию, при котором мьютексами защищено всё. Такой промежуточный режим можно включить следующим образом:
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() перестают работать.
В Unix SQLite использует pthreads для реализации мьютексов и требует рекурсивный мьютекс. Большинство современных реализаций pthread поддерживают рекурсивные мьютексы, но не все. Для систем, не поддерживающих рекурсивные мьютексы, рекомендуется использовать приложения только в однопоточном режиме. Если это невозможно, SQLite предоставляет альтернативную реализацию рекурсивного мьютекса, построенную на основе стандартных «быстрых» мьютексов pthreads. Эта альтернативная реализация должна работать правильно, если pthread_equal() является атомарной операцией, а процессор имеет когерентный кэш данных. Альтернативная реализация рекурсивного мьютекса включается следующим параметром командной строки компилятора:
-DSQLITE_HOMEGROWN_RECURSIVE_MUTEX=1
3.0 Настройка или замена подсистемы выделения памяти
По умолчанию SQLite получает необходимую ей память для объектов и кэша с помощью реализаций malloc()/free() из стандартной библиотеки. Также ведётся работа над экспериментальными распределителями памяти, которые удовлетворяют все запросы памяти за счёт единого буфера фиксированного размера, передаваемого SQLite при запуске приложения. Дополнительная информация об этих экспериментальных распределителях памяти появится в следующей редакции этого документа.
SQLite позволяет приложению указать альтернативный распределитель памяти во время выполнения: для этого нужно заполнить экземпляр объекта sqlite3_mem_methods указателями на функции альтернативной реализации, а затем зарегистрировать эту реализацию с помощью интерфейса sqlite3_config(). Например:
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. VFS можно добавлять во время выполнения с помощью интерфейса sqlite3_vfs_register().
Сборки SQLite по умолчанию для Unix, Windows и OS/2 включают VFS, подходящую для целевой платформы. Сборки SQLite для других операционных систем по умолчанию не содержат VFS, но приложение может зарегистрировать одну или несколько VFS во время выполнения.
5.0 Перенос SQLite на новую операционную систему
Чтобы перенести SQLite на новую операционную систему — то есть на операционную систему, которая не поддерживается по умолчанию, — приложение должно предоставить...
- работающую подсистему мьютексов (но только если приложение многопоточное),
- работающую подсистему выделения памяти (если в стандартной библиотеке отсутствует malloc()), и
- работающую реализацию VFS.
Всё это можно реализовать в одном дополнительном файле исходного кода на C, а затем скомпоновать его со штатным файлом исходного кода «sqlite3.c», чтобы получить работающую сборку SQLite для целевой операционной системы. Помимо альтернативных подсистем мьютексов и выделения памяти, а также новой VFS, дополнительный файл исходного кода на C должен содержать реализации следующих двух функций:
Файл исходного кода «sqlite3.c» содержит реализации VFS, а также функций sqlite3_initialize() и sqlite3_shutdown() по умолчанию, подходящие для Unix, Windows и OS/2. Чтобы при компиляции sqlite3.c не загружался один из этих компонентов по умолчанию, необходимо добавить следующий параметр времени компиляции:
-DSQLITE_OS_OTHER=1
Ядро SQLite вызовет sqlite3_initialize() на раннем этапе. Дополнительный файл исходного кода на C может содержать реализацию sqlite3_initialize(), которая регистрирует подходящую VFS, а также, возможно, инициализирует альтернативную систему мьютексов (если мьютексы необходимы) или выполняет требуемую инициализацию подсистемы выделения памяти. Ядро SQLite никогда не вызывает sqlite3_shutdown(), но эта функция входит в официальный API SQLite и не предоставляется иным образом при компиляции с параметром -DSQLITE_OS_OTHER=1, поэтому для полноты реализации дополнительный файл исходного кода на C, вероятно, должен содержать её реализацию.
Последнее обновление этой страницы: 2026-03-24 11:35:08Z
SQLite is in the Public Domain.
https://sqlite.org/custombuild.html