SQLite поддерживает неограниченное количество одновременных читателей, но в любой момент времени может работать только один писатель. Для многих ситуаций это не проблема. Писатель в очереди. Каждое приложение выполняет свою работу базы данных быстро и движется дальше, и никакая блокировка не длится более нескольких десятков миллисекунд. Но есть некоторые приложения, которые требуют большего параллелизма, и эти приложения могут нуждаться в поиске другого решения.
Это ясно в DOC.
В обработке транзакций SQLite реализует независимую обработку транзакций через эксклюзивные и общие блокировки на уровне базы данных. И именно поэтому несколько процессов могут считывать данные из одной и той же базы данных одновременно, но только один может записывать в базу данных.
Исключительная блокировка должна быть получена до того, как процесс или поток захотят выполнить операцию записи в базу данных. После получения исключительной блокировки другие операции чтения или записи больше не будут выполняться.
Реализовать детали для экземпляра два, напишите:
В SQLite есть таблица блокировок, позволяющая в последний момент заблокировать различные базы данных записи для обеспечения максимального параллелизма.
Исходное состояние «UNLOCKED», и в этом состоянии соединение еще не имеет доступа к базе данных. Когда база данных подключена к базе данных и даже транзакция была запущена с BEGIN, соединение все еще находится в состоянии «UNLOCKED».
Следующим состоянием разблокированного состояния является состояние SHARED. Чтобы иметь возможность считывать (не записывать) данные из базы данных, соединение должно сначала войти в состояние SHARED, то есть сначала получить блокировку SHARED.
Несколько соединений могут одновременно получать и поддерживать блокировки SHARED, то есть несколько соединений могут одновременно считывать данные из одной и той же базы данных. Но даже если не была снята только одна блокировка SHARED, она не позволяет любому соединению записывать базу данных.
Если соединение хочет записать базу данных, оно должно сначала получить зарезервированную блокировку.
Одновременно может быть активна только одна зарезервированная блокировка, хотя несколько блокировок SHARED могут сосуществовать с одной зарезервированной блокировкой. RESERVED отличается от PENDING тем, что новые замки SHARED могут быть получены при наличии зарезервированного замка.
Как только соединение получает блокировку RESERVED, оно может начать обработку операций модификации базы данных, хотя эти изменения могут быть выполнены только в буфере, а не фактически записаны на диск. Изменения, внесенные в содержимое считывания, сохраняются в буфере памяти.
Когда соединение хочет отправить модификацию (или транзакцию), необходимо обновить зарезервированную блокировку до эксклюзивной блокировки. Чтобы получить блокировку, вы должны сначала снять блокировку до ожидающей блокировки.
Блокировка PENDING означает, что процесс, удерживающий блокировку, хочет записать в базу данных как можно скорее и просто ожидает от всех текущих блокировок SHARED, чтобы снять, чтобы он мог получить блокировку EXCLUSIVE. Новые блокировки SHARED не разрешены для базы данных, если активна блокировка PENDING, хотя существующие блокировки SHARED могут продолжаться.
ЭКСКЛЮЗИВНАЯ блокировка необходима для записи в файл базы данных. Только одна ИСКЛЮЧИТЕЛЬНАЯ блокировка разрешена для файла, и никакие другие блокировки любого рода не могут сосуществовать с ИСКЛЮЧИТЕЛЬНОЙ блокировкой. Чтобы максимизировать параллелизм, SQLite работает, чтобы минимизировать время, в течение которого удерживаются ИСКЛЮЧИТЕЛЬНЫЕ блокировки.
Таким образом, SQLite безопасно обрабатывает параллельный доступ несколькими процессами, пишущими из одного и того же БД, потому что он его не поддерживает. Вы получите SQLITE_BUSY
или SQLITE_LOCKED
для второго записывающего устройства, когда оно достигнет ограничения повторных попыток.