SQLite3 и несколько процессов

Как обеспечить правильность, когда несколько процессов обращаются к одному файлу базы данных SQLite?

Ответы

Ответ 1

Во-первых, избегайте одновременного доступа к файлам базы данных sqlite. Concurrency является одной из слабых точек sqlite, и если у вас есть очень параллельное приложение, рассмотрите возможность использования другого механизма базы данных.

Если вы не можете избежать Concurrency или отказаться от sqlite, заверните транзакции записи в BEGIN IMMEDIATE;... END;. Режим транзакции по умолчанию в sqlite равен DEFERRED, что означает, что блокировка получена только при первой попытке реальной записи. При транзакциях IMMEDIATE блокировка немедленно приобретается или вы получаете SQLITE_BUSY немедленно. Когда кто-то держит блокировку в базе данных, другие попытки блокировки приведут к SQLITE_BUSY.

Работа с SQLITE_BUSY - это то, что вам нужно решить самостоятельно. Для многих приложений ожидание второго или двух, а затем повторных попыток работает совершенно нормально, отказ после n неудачных попыток. Есть помощники API sqlite3, которые делают это легко, например. sqlite3_busy_handler() и sqlite3_busy_timeout(), но это также можно сделать вручную.

Вы также можете использовать синхронизацию уровня ОС, чтобы получить блокировку мьютекса в базе данных или использовать обмен сообщениями между потоками/межпроцессорными сообщениями уровня OS, чтобы сигнализировать, когда один поток выполняется для доступа к базе данных.

Ответ 2

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

В качестве альтернативы вы можете использовать синхронизацию ОС - mutex в MS Windows или что-то подобное на других ОС. Этот процесс попытается получить мьютекс, и если кто-то еще его удерживает, процесс будет заблокирован до тех пор, пока другой процесс не завершит операцию и не выпустит мьютекс. Следует соблюдать осторожность, чтобы предотвратить случаи, когда процесс получает мьютекст, а затем никогда не выпускает его.

Ответ 3

В основном вам необходимо обернуть код доступа к данным с помощью транзакций. Это будет поддерживать ваши данные. Больше ничего не требуется.

В SQLite вы используете

НАЧАТЬ ПЕРЕДАЧУ

COMMIT TRANSACTION

чтобы разграничить транзакции. Поместите ваш код SQL между ними, чтобы он выполнялся в одной транзакции.

Однако, поскольку предыдущие люди прокомментировали передо мной - вам нужно обратить пристальное внимание на проблемы concurrency. SQLite может работать достаточно быстро, если он используется для доступа к чтению (несколько считывателей не блокируются и могут запускаться одновременно).

Однако - изображение значительно изменяется, если ваш код чередует доступ на запись и чтение. С SQLite - весь файл базы данных будет заблокирован, если активен только один писатель.

Ответ 4

Часто задаваемые вопросы SQLite о this