Spec-Zone.ru › SQLite

Модуль асинхронного ввода-вывода для SQLite

ПРИМЕЧАНИЕ: Режим WAL с PRAGMA synchronous, установленным в NORMAL, избегает вызовов fsync() во время фиксации транзакции и вызывает fsync() только во время операции чекпоинта. Использование режима WAL в значительной степени сводит на нет необходимость в этом модуле асинхронного ввода-вывода. Следовательно, этот модуль больше не поддерживается. Исходный код по-прежнему существует в дереве исходных текстов SQLite, но он не входит в стандартную сборку и больше не поддерживается. Данная документация сохраняется для исторической справки.

Обычно, когда SQLite записывает в файл базы данных, он ожидает завершения операции записи перед возвращением управления вызывающему приложению. Поскольку запись в файловую систему обычно очень медленная по сравнению с операциями, связанными с процессором, это может быть узким местом производительности. Асинхронный бэкенд ввода-вывода — это расширение, которое заставляет SQLite выполнять все запросы на запись с помощью отдельного потока, работающего в фоновом режиме. Хотя это не уменьшает общие системные ресурсы (процессор, пропускная способность диска и т. д.), это позволяет SQLite быстро вернуть управление вызывающей стороне, даже когда происходит запись в базу данных.

1.0 ФУНКЦИОНАЛЬНОСТЬ

При асинхронном вводе-выводе запросы на запись обрабатываются отдельным потоком в фоновом режиме. Это означает, что поток, который инициирует запись в базу данных, не должен ждать (иногда медленной) операции ввода-вывода с диском. Запись, кажется, происходит очень быстро, хотя на самом деле она происходит со своей обычной медленной скоростью в фоновом режиме.

Асинхронный ввод-вывод, кажется, обеспечивает лучшую отзывчивость, но есть и цена. Вы теряете свойство Долговечность. При стандартном бэкенде ввода-вывода SQLite, после завершения записи вы знаете, что записанная информация надежно сохранена на диске. При асинхронном вводе-вывода это не так. Если ваша программа аварийно завершится или произойдет отключение питания после записи в базу данных, но до завершения асинхронного потока записи, то изменение базы данных может никогда не попасть на диск, и следующий пользователь базы данных может не увидеть ваше изменение.

Вы теряете Долговечность с асинхронным вводом-выводом, но сохраняете другие части ACID: Атомарность, Согласованность и Изолированность. Многие приложения прекрасно работают без Долговечности.

1.1 Как это работает

Асинхронный ввод-вывод работает путем создания объекта SQLite VFS и его регистрации с помощью sqlite3_vfs_register(). Когда файлы, открытые через этот VFS, записываются (с помощью метода vfs xWrite()), данные не записываются непосредственно на диск, а помещаются в «очередь записи», чтобы их обработала фоновая нить.

Когда файлы, открытые с асинхронным VFS, считываются (с помощью метода vfs xRead()), данные считываются с диска и из очереди записи, так что с точки зрения читателя vfs метод xWrite() уже, кажется, завершен.

Асинхронный VFS ввода-вывода регистрируется (и аннулируется) с помощью вызовов функций API sqlite3async_initialize() и sqlite3async_shutdown(). Подробности см. в разделе «Компиляция и использование» ниже.

1.2 Ограничения

Для того, чтобы получить опыт работы с основными идеями, связанными с асинхронным вводом-выводом, эта реализация намеренно упрощена. Дополнительные возможности могут быть добавлены в будущем.

Например, в текущей реализации, если записи происходят в непрерывном потоке, который превышает возможности фоновой нити записи ввода-вывода, очередь ожидающих операций записи будет расти без ограничений. Если это будет продолжаться достаточно долго, у системы может закончится память. Более сложный модуль мог бы отслеживать количество ожидающих записей и прекращать прием новых запросов на запись, когда очередь ожидающих записей становится слишком большой.

1.3 Блокировка и конкурентность

Несколько подключений из одного процесса, использующие эту реализацию асинхронного ввода-вывода, могут одновременно обращаться к одному файлу базы данных. С точки зрения пользователя, если все подключения из одного процесса, нет никакой разницы между конкурентностью, предлагаемой «нормальным» SQLite и SQLite, использующим асинхронный бэкенд.

Если включена блокировка файлов (по умолчанию включена), то подключения из разных процессов также могут читать и писать в файл базы данных. Однако конкурентность уменьшается следующим образом:

  • Когда подключение, использующее асинхронный ввод-вывод, начинает транзакцию базы данных, база данных блокируется немедленно. Однако блокировка не снимается до тех пор, пока все соответствующие операции в очереди записи не будут записаны на диск. Это означает (например), что база данных может оставаться заблокированной некоторое время после того, как выдан «COMMIT» или «ROLLBACK».

  • Если приложение, использующее асинхронный ввод-вывод, выполняет транзакции друг за другом, другие пользователи базы данных могут фактически быть заблокированы от доступа к базе данных. Это потому, что когда выполняется BEGIN, блокировка базы данных устанавливается немедленно. Но когда происходит соответствующий COMMIT или ROLLBACK, блокировка не снимается до тех пор, пока соответствующая часть очереди записи не будет обработана. В результате, если COMMIT следует за BEGIN перед обработкой очереди записи, база данных никогда не разблокируется, предотвращая доступ других процессов к базе данных.

Блокировка файлов может быть отключена во время выполнения с помощью API sqlite3async_control() (см. ниже). Это может улучшить производительность при использовании NFS или других сетевых файловых систем, так как синхронные обмены с сервером, необходимые для установления блокировок файлов, будут избегаться. Однако, если несколько подключений попытаются получить доступ к одному файлу базы данных при отключенной блокировке файлов, скорее всего произойдут аварийные завершения приложения и повреждение базы данных.

2.0 КОМПИЛЯЦИЯ И ИСПОЛЬЗОВАНИЕ

Расширение асинхронного ввода-вывода состоит из одного файла кода на C (sqlite3async.c) и файла заголовков (sqlite3async.h), расположенных в ext/async/ подпапке дерева исходных текстов SQLite, который определяет API на C, используемый приложениями для активации и управления функциональностью модуля.

Для использования расширения асинхронного ввода-вывода, необходимо скомпилировать sqlite3async.c как часть приложения, использующего SQLite. Затем используйте API, определенные в sqlite3async.h, для инициализации и настройки модуля.

API асинхронного ввода-вывода VFS подробно описаны в комментариях в sqlite3async.h. Использование API обычно включает следующие шаги:

  1. Зарегистрировать асинхронный VFS ввода-вывода в SQLite, вызвав функцию sqlite3async_initialize().

  2. Создать фоновый поток для выполнения операций записи и вызвать sqlite3async_run().

  3. Использовать стандартный API SQLite для чтения и записи в базы данных через асинхронный VFS ввода-вывода.

Подробности см. в комментариях в файле заголовков sqlite3async.h.

3.0 ПЕРЕНОСИМОСТЬ

В настоящее время расширение асинхронного ввода-вывода совместимо с системами win32 и системами, поддерживающими интерфейс pthreads, включая Mac OS X, Linux и другие типы Unix.

Для переноса расширения асинхронного ввода-вывода на другую платформу пользователь должен реализовать примитивы мьютексов и событий для новой платформы. В настоящее время нет внешнего доступного интерфейса для этого, но изменение кода в файле sqlite3async.c для включения примитивов конкурентности новых платформ относительно просто. Найдите комментарий «PORTING FUNCTIONS» в файле sqlite3async.c для получения подробностей. Затем реализуйте новые версии каждого из следующих:

static void async_mutex_enter(int eMutex);
static void async_mutex_leave(int eMutex);
static void async_cond_wait(int eCond, int eMutex);
static void async_cond_signal(int eCond);
static void async_sched_yield(void);

Требуемая функциональность каждой из вышеперечисленных функций описана в комментариях в sqlite3async.c.

Эта страница была в последний раз изменена 10.10.2023 17:29:48 UTC

SQLite is in the Public Domain.
https://sqlite.org/asyncvfs.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API