Я разрабатываю приложение с SQLite как базу данных, и у меня есть небольшая проблема с пониманием того, как использовать его в нескольких потоках (к сожалению, мне не помогли ни один из других вопросов переполнения стека).Как использовать SQLite в многопоточном приложении?
Мой прецедент: в базе данных есть одна таблица, назовем ее «A», которая имеет разные группы строк (на основе одного из их столбцов). У меня есть «основной поток» приложения, который читает содержимое из таблицы A. Кроме того, я иногда решает обновить определенную группу строк. Для этого я хочу создать новый поток, удалить все строки группы и повторно вставить их (это единственный способ сделать это в контексте моего приложения). Это может произойти с разными группами одновременно, поэтому у меня может быть 2+ потока, пытающихся обновить базу данных.
Я использую разные транзакции из каждой темы, I.E. в начале цикла обновления каждого потока у меня есть начало. Фактически, каждый поток фактически выполняет вызов «BEGIN», удаляет из базы данных все строки, необходимые для «обновления», и вставляет их снова с новыми значениями (это так, как это должно быть сделано в контексте моего заявление).
Теперь я пытаюсь понять, как я реализую это. Я пробовал читать (другие ответы на Stack Overflow, сайт SQLite), но я не нашел ответы на все вопросы. Вот некоторые вещи, о которых мне интересно:
- Нужно ли мне называть «открывать» и создавать новую структуру sqlite из каждого потока?
- Должен ли я добавить какой-либо специальный код для всего этого или достаточно, чтобы порождать разные потоки, обновлять строки, и это нормально (поскольку я использую разные транзакции)?
- Я видел что-то, говоря о разных типах блокировок, и о том, что я мог бы получить «SQLite занят» от вызова определенных API, но, честно говоря, я не видел ссылок, которые полностью объяснялись, когда мне нужно было все это в учетную запись. Нужно ли мне?
Если кто-нибудь может ответить на вопросы/указать мне в сторону хорошего ресурса, я был бы очень благодарен.
ОБНОВЛЕНИЕ 1: Из всего, что я читал до сих пор, похоже, что у вас не может быть двух потоков, которые все равно будут писать в файл базы данных.
См.: http://www.sqlite.org/lockingv3.html. В разделе 3.0: ЗАБРОНИРОВАННАЯ блокировка означает, что процесс планирует записать в файл базы данных в какой-то момент в будущем, но в настоящее время он просто считывает из файла. За один раз может быть активен только один замок RESERVED, хотя несколько замков SHARED могут сосуществовать с одной блокировкой RESERVED.
Означает ли это, что я могу также создавать только один поток, чтобы обновлять группу строк каждый раз? У меня есть какой-то поток poller, который решает, что мне нужно обновить некоторые из строк, а затем создает новый поток для этого, но не более одного за раз? Так как это похоже на то, что любой другой поток, который я создаю, просто получит SQLITE_BUSY до тех пор, пока первый поток не закончится.
Правильно ли я понял вещи?
Кстати, спасибо за ответы, они помогли много.
Не могли бы вы уточнить, почему вы должны УДАЛИТЬ строки и вставлять их вместо того, чтобы просто делать ОБНОВЛЕНИЕ? Я спрашиваю, потому что это похоже на окольный способ делать вещи, и может быть более простое решение. – Wernsey
Причина в том, что разные строки представляют собой, в основном, коллекцию фрагментов данных. То, что делают потоки, это вспоминать, что данные с нуля каждый раз, когда мы решаем, что нам нужно (нет способа обновить существующие данные).Каждый раз, когда мы вспоминаем, мы можем получить различное количество информации и даже совершенно разные данные, поэтому единственный способ просто удалить все, что мы вспомнили. –
Как идея, намного быстрее просто отбросить стол и воссоздать его, если вы планируете каждый раз удалять все строки. – Snazzer