Подтвердить что ты не робот

Одновременное чтение и запись SQLite

Я прочитал много тем, но не могу понять ответ на вопрос: возможно ли читать и писать одновременно?

У меня есть фоновый поток, который обновляет некоторые данные, а пользовательский интерфейс требует небольшого объема данных, хранящихся в БД. Таким образом, в выполнении пользовательского интерфейса выполняется операция SELECT. Но он блокируется при обновлении. В результате пользовательский интерфейс замерзает в течение нескольких секунд.

Кто-нибудь имеет успех при чтении из БД при написании?


Его можно читать и писать в БД на iPhone. Есть ли причина такой разницы в синхронной реализации оболочки на собственные функции sqlite?

4b9b3361

Ответ 1

В Android 3.0 и выше SQLiteDatabases поддерживают режим WAL (запись на запись):

Если запись на запись не включена (по умолчанию), это не возможно для чтения и записи в базе данных в то же время время. Перед изменением базы данных автор неявно приобретает исключительная блокировка базы данных, которая препятствует доступу читателей базы данных до тех пор, пока запись не будет завершена.

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

http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#enableWriteAheadLogging()

Чтобы начать транзакцию в режиме WAL, используйте beginTransactionNonExclusive() вместо beginTransaction(). В то время как beginTransaction() запускает транзакцию в режиме EXCLUSIVE, beginTransactionNonExclusive() запускает одно в режиме IMMEDIATE

  • В режиме EXCLUSIVE используются эксклюзивные блокировки (http://www.sqlite.org/lockingv3.html#excl_lock), что означает, что никакое другое соединение с базой данных, кроме подключений read_uncommitted, сможет читать базу данных и нет другое соединение без исключения сможет записывать базу данных до завершения транзакции.
  • Режим IMMEDIATE использует зарезервированные блокировки (http://www.sqlite.org/lockingv3.html#reserved_lock), что означает, что никакое другое соединение с базой данных не сможет записать в базу данных или выполнить НАЧАТЬ НЕМЕДЛЕННО или BEGIN EXCLUSIVE, однако другие процессы могут продолжать читать из базы данных.

В простых словах: call beginTransactionNonExclusive() для режима IMMEDIATE, и мы можем читать, пока записывается другой поток (состояние до начала транзакции записи, потому что мы не будем использовать read_uncommitted connections → <а3 > ).

Ответ 2

Вы не можете читать и писать одновременно. SQLite - это безсерверная файловая база данных.

Из SQLite FAQ:

"Когда какой-либо процесс хочет писать, он должен заблокировать весь файл базы данных на время его обновления, но обычно это занимает всего несколько миллисекунд. Другие процессы просто ждут завершения записи, а затем продолжат свою деятельность. встроенные механизмы СУБД SQL обычно позволяют только одному процессу напрямую подключаться к базе данных."

Ответ 3

Начиная с API 11 Android поддерживает WAL-режим. Он сохраняет исходные данные незатронутыми во время транзакции, поэтому другие потоки могут читать, когда транзакция выполняется. Вы можете проверить мою статью для получения более подробной информации о режиме WAL:

http://www.skoumal.net/en/parallel-read-and-write-in-sqlite/

Вам также следует избегать запуска запросов к базе данных в потоке пользовательского интерфейса. Он всегда может стать вялым и блокировать ваш пользовательский интерфейс.

Ответ 4

Невозможно читать и писать одновременно. Однако, если у вас правильно настроены классы базы данных SQLite (один экземпляр вашего DB и вспомогательных классов), разные потоки должны иметь возможность синхронно захватывать соединение с БД, чтобы не было заметного отставания.

Также звучит так, как будто вы пытаетесь сделать бэкэнд-работу (напишите в db) с помощью потока пользовательского интерфейса. Вы не должны этого делать. Создайте AsyncTask, чтобы обрабатывать это, вместо того, чтобы ваш поток пользовательского интерфейса обрабатывал его.

Обратитесь к документации SQLiteOpenHelper. Вот предыдущая статья, которая говорит об этом также: Каковы лучшие практики для SQLite на Android?