SQLite3 и несколько процессов - PullRequest
18 голосов
/ 30 июня 2009

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

Ответы [ 4 ]

15 голосов
/ 30 июня 2009

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

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

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

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

2 голосов
/ 27 июля 2009

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

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

НАЧАЛО СДЕЛКИ

совершение сделки

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

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

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

2 голосов
/ 30 июня 2009

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

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

0 голосов
/ 30 июня 2009

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

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