SQLite3 и многопроцессорность - PullRequest
4 голосов
/ 07 августа 2011

Я заметил, что sqlite3 на самом деле не способен и не надежен, когда я использую его в многопроцессорной среде.Каждый процесс пытается записать некоторые данные в одну и ту же базу данных, чтобы соединение использовалось несколькими потоками.Я попробовал это с опцией check_same_thread = False, но количество вставок довольно случайное: иногда оно включает все, иногда нет.Должен ли я параллельно обрабатывать только части функции (извлекать данные из Интернета), складывать их выходные данные в список и помещать их в таблицу вместе, или есть надежный способ обработки нескольких соединений с помощью sqlite?

Ответы [ 4 ]

7 голосов
/ 07 августа 2011

Прежде всего, существует разница между многопроцессорностью (несколько процессов) и многопоточностью (несколько потоков внутри одного процесса).

Кажется, вы говорите о многопоточности здесь. Есть несколько предостережений, о которых вы должны знать, когда используете SQLite в многопоточной среде. В документации SQLite упоминается следующее:

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

Более подробную информацию см. Здесь: Является ли SQLite поточно-ориентированным?

3 голосов
/ 10 октября 2012

Я только что работал над чем-то очень похожим:

  • несколько процессов (для меня пул обработки от 4 до 32 рабочих)
  • каждый рабочий процесса делает некоторые вещи, которые включают получение информации из интернета (вызов Алхимического API для меня)
  • каждый процесс открывает свое собственное соединение sqlite3, все в один файл, и каждый процесс добавляет одну запись, прежде чем получить следующую задачу из стека

Сначала я подумал, что вижу ту же проблему, что и вы, затем проследил ее до дублирующих и противоречивых проблем с получением информации из Интернета. Так как я был там, я провел некоторое тестирование пыток в sqlite и многопроцессорном режиме и обнаружил, что могу запускать МНОГИЕ рабочие процесса, все соединения и добавления в один и тот же файл sqlite без координации, и это было просто, когда я просто вводил данные теста.

Так что теперь я смотрю на вашу фразу "(выборка данных из Интернета)" - возможно, вы могли бы попробовать заменить выборку этих данных на некоторые фиктивные данные, чтобы убедиться, что это действительно соединение sqlite3, вызывающее у вас проблемы. По крайней мере, в моем тестируемом случае (запущенном прямо сейчас в другом окне) я обнаружил, что несколько процессов могут все добавлять через свои собственные соединения без проблем, но ваше описание точно соответствует проблеме, которая возникает у меня, когда два процесса сталкиваются друг с другом во время движения для веб-API (на самом деле очень странная ошибка) и иногда не получают ожидаемые данные, что, конечно, оставляет пустую ячейку в базе данных. Мое возможное решение состояло в том, чтобы обнаружить эту ошибку у каждого работника и повторить вызов веб-API, когда это произошло (могло бы быть более элегантно, но это было для личного взлома).

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

0 голосов
/ 07 августа 2011

sqlitedict : Облегченная оболочка для базы данных Python sqlite3, с похожим на dict интерфейсом и поддержкой многопоточного доступа.

0 голосов
/ 07 августа 2011

Если бы мне пришлось создать систему, подобную той, которую вы описываете, с использованием SQLITE, то я бы начал с написания асинхронного сервера (с использованием модуля asynchat), который обрабатывал бы весь доступ к базе данных SQLITE, а затем я бы написал другие процессы, чтобы использовать этот сервер. Когда существует только один процесс, обращающийся к файлу db напрямую, он может применять строгую последовательность запросов, чтобы не было опасности наступления двух процессов друг на друга. Это также быстрее, чем постоянное открытие и закрытие БД.

На самом деле, я бы также старался избегать ведения сеансов, иными словами, я бы попытался написать все остальные процессы, чтобы каждая транзакция базы данных была независимой. Как минимум это будет означать, что транзакция может содержать не один, а один список операторов SQL, и для этого может потребоваться даже некоторая возможность if then, чтобы вы могли ВЫБРАТЬ запись, проверить, что поле равно X, и только тогда , ОБНОВИТЬ это поле. Если ваше существующее приложение закрывает базу данных после каждой транзакции, вам не нужно беспокоиться о сеансах.

Вы можете использовать что-то вроде nosqlite http://code.google.com/p/nosqlite/

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