Android: уровни изоляции транзакций SQLite (ORMLite) - PullRequest
5 голосов
/ 12 октября 2011

Я использую ORMLite в своем проекте Android.Я знаю, что Sqlite заботится о блокировке на уровне файлов.Многие темы могут читать, можно писать.Блокировки предотвращают более одной записи.Может ли кто-нибудь объяснить, что произойдет, если один поток обновляет какую-либо запись, а другой поток пытается прочитать эту запись?Получит ли поток (который пытается прочитать) устаревшие данные?Или он будет заблокирован, пока первый поток не завершит свою операцию записи?Как я знаю, существует 4 уровня изоляции транзакций: Serializable, Repeatable read, Read commit, Read uncommittedИ есть ли способ изменить его в SQLite или ORMLite?

Ответы [ 2 ]

9 голосов
/ 12 октября 2011

SQLite имеет 5 различных уровней блокировки - http://www.sqlite.org/lockingv3.html: разблокирован, общий, зарезервированный, ожидающий, эксклюзивный.Важной блокировкой для этого вопроса является общая блокировка:

"SHARED - база данных может быть прочитана, но не записана. Любое количество процессов может одновременно удерживать блокировки SHARED, следовательно, может быть многоодновременные считыватели. Но ни одному другому потоку или процессу не разрешено выполнять запись в файл базы данных, пока активны одна или несколько блокировок SHARED.строка в БД - вся таблица заблокирована).

Таким образом, пока вы выбираете данные, никакой другой процесс не может их изменять.Шаги блокировки для чтения данных: UNLOCKED → PENDING → SHARED → UNLOCKED (вы можете запустить выбор в транзакции).Так что ситуация, когда вы выбираете что-то, а кто-то изменяет данные, не может возникнуть.

Ваш вопрос: что произойдет, если вы обновляете базу данных и делаете выбор в той же таблице?В режиме автоматической фиксации механизм блокировки для записи / обновления: UNLOCKED → PENDING → SHARED → RESERVED → PENDING → EXCLUSIVE → UNLOCKED.Находясь в эксклюзивном замке, новые читатели (соединения) не могут подключаться к базе данных.Одновременно может существовать только одна ИСКЛЮЧИТЕЛЬНАЯ блокировка.SQLite будет ждать, пока не будут сняты все другие блокировки PENDING от чтения соединений, и предотвратит любые новые.В это время начнется запись данных.

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

Отличная книга по этому вопросу - «Полное руководство по SQLite», особенно глава «Транзакции».

3 голосов
/ 12 октября 2011

SQLite поддерживает несколько разных уровней изоляции, которые можно выбрать во время компиляции и во время выполнения.

http://www.sqlite.org/threadsafe.html

Я предполагаю, что Androidite SQLite по умолчанию находится в режиме Serialized . С точки зрения многопоточного доступа, он выполняет блокировку чтения / записи на уровне файловой системы, чтобы позволить нескольким читателям, но только одному устройству записи одновременно:

http://www.sqlite.org/faq.html#q5

Однако ORMLite рекомендует настоятельно и попытался hard поддерживать единственное соединение с базой данных, поэтому проблемы с блокировкой могут быть неактуальными.

В частности, если один поток обновляет запись, а другой читает, то это условие состязания. Либо читающая ветка получит запись до обновления или после его завершения. Однако читатель не получит частично обновленные данные. Но я подозреваю, что вы это знали.

С точки зрения уровней изоляции, поддерживаемых SQLite, по умолчанию Serialized , как уже упоминалось, но похоже, что он поддерживает read-uncommitted , по крайней мере, до некоторой степени.

http://www.sqlite.org/sharedcache.html

Вы можете использовать ORMLite Dao.executeRaw () , чтобы включить его:

dao.executeRaw("PRAGMA read_uncommitted = True;");

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

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

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