как отлаживать заблокированную базу данных sqlite3 - PullRequest
4 голосов
/ 20 апреля 2011

Я пишу приложение на iOS, которое использует sqlite3, завернутый в fmdatabase. Я столкнулся с проблемой, что в какой-то момент моя программа застряла в цикле внутри библиотек FMDatabase, в частности, функции, которая вызывает sqlite3_step и обнаруживает, что база данных занята, а затем повторяет попытки снова и снова.

Я ищу общие инструменты и советы по отладке, так как здесь будет слишком много, чтобы привести всю мою настройку. Некоторые вещи, которые могут иметь значение, я открыл дескриптор базы данных для базы данных, которая уже имеет дескриптор в другом потоке. sqlite3_threadsafe () возвращает 2, поэтому я знаю, что он включен. Я также проверил это новое соединение, сделав очень простое утверждение выбора и обновления. Когда я запускаю свою программу и пытаюсь запустить обновление базы данных, я застреваю.

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

Любая помощь или советы о том, где я могу ошибаться, будет принята с благодарностью.

1 Ответ

21 голосов
/ 24 апреля 2011

SQLite блокирует базу данных вся во время операции записи (т. Е. Когда запись происходит в любую таблицу, никакая другая запись в любую таблицу в любом месте может происходить одновременно).Некоторые базы данных обеспечивают одновременную запись посредством блокировок на уровне таблиц или иногда на уровне строк.В отличие от реализации SQLite, блокировка на уровне таблицы в основном означает, что когда вы записываете данные в заданную таблицу, никакой другой поток не может одновременно записывать данные в любую запись в этой таблице (однако запись в другие таблицы можетпроисходят одновременно, в некоторых обстоятельствах).Точно так же блокировки на уровне строк делают это еще более значительным и позволяют блокировать только необходимые строки, что позволяет выполнять одновременную запись в одну и ту же таблицу из нескольких потоков.Идея здесь состоит в том, чтобы минимизировать объем данных, которые необходимо заблокировать для операции записи, что эффективно увеличивает количество одновременных записей, возможных по базе данных, и в зависимости от вашей реализации / того, как вы используете свою базу данных,это может значительно увеличить пропускную способность.

Теперь вернемся к вашему вопросу ...

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

По сути, где-то вкод, один поток пытается сделать свое обновление, прежде чем другой поток снял свою блокировку на базе данных.Это обычное препятствие для SQLite, потому что авторы / документация скажут вам, что SQLite может обрабатывать параллелизм как чемпион.Реальность такова, что то, что SQLite считает «поддержкой параллелизма», означает попытку быть очень быстрой, чтобы блокировки в базе данных удерживались только в течение очень короткого времени, и поэтому блокировки в базе данных снимались до истечения времени ожидания.Во многих случаях это работает просто отлично и никогда не мешает вам.Однако наличие очень кратковременных блокировок - это не то же самое, что 1014 *, что фактически позволяет одновременную запись из нескольких потоков.

Думайте об этом как о том, как iOS выполняет многозадачность (по крайней мере, в iOS 5)., когда я пишу это) - на самом деле он ставит другие приложения на паузу и возвращается к ним.Это приводит к тому, что (а) срок службы батареи намного лучше из-за более низкой загрузки процессора, и (б) вам не нужно запускать приложение с нуля при каждом его запуске.Это замечательно, но само слово «многозадачность», используемое в iOS, технически не означает то же самое, что и «многозадачность» в других средах (даже Mac OS X).

SQLite - то же самое.Есть ли у них поддержка "параллелизма"?Ну, вроде как, но то, как они определяют слово «параллелизм», не то, как остальной мир БД определяет «параллелизм».

Никто не ошибается, но в подобных случаях он добавляетдо реализации путаницы.

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