SQLite с двумя процессами Python, обращающимися к нему: одно чтение, одно письмо

22

Я разрабатываю небольшую систему с двумя компонентами: один опрашивает данные с интернет-ресурса и переводит их в данные sql, чтобы сохранить их локально; второй читает эти данные sql из локального экземпляра и передает их через json и остальные API.

Первоначально я планировал сохранить данные с помощью postgresql, но поскольку приложение будет иметь очень небольшой объем данных для хранения и трафика для обслуживания, я подумал, что это излишне. SQLite подходит для работы? Мне нравится идея малого размера, и мне не нужно поддерживать еще один сервер sql для этой задачи, но я обеспокоен параллелизмом.

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

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

бб
источник
3
@gnat Круто. Может ли один экземпляр SQLite поддерживать два параллельных процесса, обращающихся к нему, если только один читает, а другой пишет? Я начал писать код, но мне было интересно, если это неправильное применение SQLite.
BB
Просто один на один. В моей предыдущей компании мы использовали SQL (как MS, так и Oracle Express) для некоторого хранилища, и мы всегда чувствовали, что с тем небольшим количеством хранимых данных нам не нужна полная БД. Поэтому в одном из релизов мы решили сделать именно то, что вы делаете. Замените эти продукты SQLite. У нас было одно и то же: один модуль записи, который собирал данные на диск и обновлял TOC на основе SQL, а также считыватель (несколько потоков), который считывал бы TOC, чтобы определить, какие данные следует извлечь. Не знаю насчет SQLite в наши дни, но то, с каким небольшим параллелизмом мы столкнулись, оказалось серьезной болью ...
ДХМ
... сзади. Я не помню всех деталей, но я думаю, что когда один процесс попытался получить блокировку и не смог, потому что другой читал, он спал бы что-то сумасшедшее, например, 20-30 секунд. Мы закончили тем, что создали специальный поток, который отвечал за доступ к SQLite, и затем у нас были оба наших процесса и все потоки в них, сериализовавшие их запросы БД в этот один поток. Оглядываясь назад, я бы, наверное, больше не пошел с SQLite.
ДХМ
1
@DXM спасибо за предупреждение, но после нескольких тестов я не столкнулся ни с чем подобным. Я знаю, что sqlite претерпел серьезную перестройку с версией 3, которая была примерно в 2004 году, поэтому мне интересно, если ваш отрицательный опыт восходит к тому времени.
BB
1
... сами, а не полагаться на схемы блокировки SQLite. Я не делал работу сам, это была другая команда, но я держал в курсе, главным образом, чтобы обеспечить обратную связь и из любопытства. Я также вошел в сеть и сделал некоторое независимое чтение и нашел оригинальную страницу автора. Прочитав это, у меня сложилось впечатление, что изобретатель SQLite просто ненавидел потоки и не понимал, почему кто-то будет их использовать, поэтому: а) БД не была разработана с учетом этих требований, и б) были добавлены блокировки / защита / взломан как запоздалая мысль, потому что слишком много людей просили об этом.
ДХМ

Ответы:

25

Вы ищете документацию по блокировке файлов и параллелизму .

Процессы SQLite используют серию блокировок для обработки параллелизма; читать, несколько процессов могут получить SHAREDблокировку.

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

Поскольку процессу записи необходимо блокировать файл базы данных только для фактических операций записи (сброса памяти, фиксации), установка с одним считывателем и только одним модулем записи будет работать достаточно хорошо. Я ожидаю, что он будет работать так же хорошо, если не лучше, как установка с одним процессом, выполняющим все чтение и запись.

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

Мартейн Питерс
источник
Спасибо за исчерпывающий ответ Martijn! У меня есть несколько сценариев для проведения некоторого тестирования, и кажется, что два процесса будут счастливо читать и записывать один экземпляр sqlite одновременно. Я выполнял параллельные запросы на чтение и запись, которые запускались каждую 1/100 секунды, и до сих пор не получил исключение заблокированных БД. Как ни странно, единственное время, когда я получал сообщение об ошибке «заблокирована база данных», было при попытке вручную (с помощью клиента командной строки sqlite3) удалить несколько строк, в то время как запросы на чтение запускались из моего сценария с 1/100 секунды. Интересно, если pysql автоматически повторяет запись после такой ошибки.
BB
10

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

бб
источник