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