Синхронизировать базу данных sqlite в target-C - PullRequest
1 голос
/ 25 января 2012

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

ПРИМЕЧАНИЕ: обе операции находятся в разных таблицах, т.е. я пишу в другой таблице и читаю из другой таблицы.

Поддерживает ли sqlite многопоточность, если да, то как я могу удалитьзаблокировать из базы данных?

Ответы [ 3 ]

3 голосов
/ 25 мая 2012

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

Если вы обращаетесь к SQLite из нескольких потоков в Objective-C, вы должны использовать какой-то механизм блокировкикоординировать доступ к дескриптору базы данных.Одним из вариантов является ключевое слово @synchronized.

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

Один из вариантов -поместить две таблицы в две разные базы данных и создать два разных подключения к ним.

Дополнительные сведения о природе использования SQLite в многопоточной среде:

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

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

3 голосов
/ 25 января 2012

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

EDIT: передать объект sqlite3 (тот, который sqlite3_open() возвращает в качестве второго параметра) в поток вместо повторного открытия базы данных в потоке. Как то так:

sqlite3 *MyDatabase; //Initialized somewhere
NSArray *DataForThread = [NSArray arrayWithObjects:
    request,
    [NSValue valueWithPointer: MyDatabase],
    nil];

[self performSelectorInBackground:@selector(processResponseInBackground:)        withObject:DataForThread];

Внутри потока восстановите объект SQLite3 следующим образом:

sqlite3 *MyDatabase = [[ThreadData objectAtIndex:1] pointerValue];
1 голос
/ 12 января 2014

Sqlite поддерживает многопоточность в смысле «писать так быстро, чтобы избежать проблем параллелизма». Реальность такова, что не должно быть проблем с блокировкой в ​​случае запросов только для чтения, но если вы хотите написать тоже ... вы можете встретить ошибку SQLITE_BUSY. Вы можете избежать этого несколькими способами:

  • либо все запросы выполняются в одном потоке (но если бы вы могли это сделать ... нет вопросов по stackoverflow :-))

  • или, как упоминалось выше, разделить таблицы базы данных на два или более файлов (сгруппировать таблицы с меньшим количеством параллельных обращений или с доступом только для чтения) и создать для каждого файла отдельное соединение БД

  • или, как упомянуто выше, используя подход синхронизации потоков для каждого метода (или блока кода), который выполняет запрос (чтобы быть уверенным, что дБ будет заблокирован при запуске транзакции, используйте «BEGIN IMMEDIATE TRANSACTION» )

  • или обработайте ошибку sqlite: busy с помощью двух обратных вызовов, предоставляемых c api, "sqlite_busy_handler" и "sqlite_busy_timeout"

  • или, после получения ошибок блокировки, подождите 1-2 секунды и повторите попытку (я думаю, лучше приблизиться к точке выше)

Я предпочитаю уменьшить количество параллельных разделений, а затем при необходимости синхронизировать доступ потоков к коду запроса. Это просто твой выбор ...

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