Соединения и блокировка SQLite - PullRequest
8 голосов
/ 03 ноября 2011

Я хотел бы получить доступ к базе данных SQLite из 2 разных потоков, тем самым используя 2 разных соединения с базой данных. Оба потока в основном будут выполнять чтение из БД и будут записывать в БД только изредка. Если я чувствую, что шансы противоречат обоим потокам, записывающим в БД одновременно, должен ли я чувствовать себя в безопасности, чтобы у меня не возникало проблем в этом сценарии?

Ответы [ 3 ]

9 голосов
/ 03 ноября 2011

Не совсем верно. Пожалуйста, смотрите мой длинный ответ здесь:

Каковы лучшие практики для SQLite на Android?

Вы не повредите свою базу данных, но если два разных потока с двумя разными подключениями попытаются записать в БД одновременно, у вас будут проблемы. Один "проиграет". Они не будут ждать, чтобы запустить в порядке. Если вы вызовете «insert» вместо «insertOrThrow», вы даже не получите исключение. Вы просто не будете писать в БД.

Вот как работает Sqlite в Android. Каждый экземпляр SqliteOpenHelper имеет 1 подключение к базе данных. Неважно, сколько раз вы вызываете 'getRead / WriteableDatabase'. Один помощник, одно соединение. Кроме того, в коде соединения Android sqlite реализована собственная блокировка потоков, поэтому, если вы используете тот же SqliteOpenHelper и, соответственно, то же соединение, все будет в порядке.

Если, однако, вы используете более одного помощника, вы можете быть не в порядке.

Я подозреваю, что у вас может быть несколько потоков, читающих и 1, пишущих, и получится нормально, но я не проверял это.

Используете ли вы несколько потоков для записи производительности? Если это так, я бы предложил просто оптимизировать использование «транзакций». Если вы делаете несколько независимых записей, это ОЧЕНЬ медленно. Если вы упаковываете их все в пакет, это очень быстро (относительно). Я подозреваю, что это происходит потому, что при каждой независимой записи Android сбрасывается на диск (что очень медленно). Если вы делаете их в кучу, все изменения вносятся в 1 запись.

Что касается поддержки 1 экземпляра помощника, вот мой недавний пост в блоге об этом:

http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection

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

http://touchlabblog.tumblr.com/post/24474455802/ormlite-for-android

Для полноты ссылок мой пост в блоге о блокировке sqlite и множественных соединениях:

http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking

6 голосов
/ 03 ноября 2011

SQLite является потокобезопасным, и в последних версиях вы можете использовать одно соединение между потоками.Тем не менее, часто задаваемые вопросы по SQLite гласят: «Потоки - это зло» (я не думаю, что они имеют в виду это в контексте SQLite, но как общее утверждение).

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

0 голосов
/ 03 ноября 2011

SQLite явно не ориентирован на многопотоковое исполнение, поэтому при этом вы можете ожидать повреждения данных.

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

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

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