SQLite з двома процесами python, що мають доступ до нього: одне читання, одне написання


22

Я розробляю невелику систему з двома компонентами: один опитує дані з Інтернет-ресурсу і переводить їх у дані sql, щоб зберегти їх на локальному рівні; другий читає ці sql дані з локального примірника та подає їх через json та спокійний api.

Спочатку я планував зберігати дані за допомогою postgresql, але оскільки у додатку буде дуже низький обсяг даних для зберігання та трафіку для обслуговування, я вважав, що це надмірно. Чи відповідає SQLite завдання? Мені подобається ідея невеликого сліду і не потрібно підтримувати ще один сервер sql для цього одного завдання, але мене турбує паралельність.

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

Чи може один екземпляр SQLite підтримувати два одночасні процеси, що мають доступ до нього, якщо тільки один читає, а другий пише? Я почав писати код, але цікавився, чи це неправильне застосування SQLite.


3
@gnat Cool. Чи може один екземпляр SQLite підтримувати два одночасні процеси, що мають доступ до нього, якщо тільки один читає, а другий пише? Я почав писати код, але цікавився, чи це неправильне застосування SQLite.
bb

Просто голови вгору. У моїй попередній компанії ми використовували SQL (як MS, так і Oracle Express) для деякого сховища, і ми завжди вважали, що при тому, що мало ми зберігаємо, нам не потрібен повний БД. Тож в одному з випусків ми вирішили зробити саме те, що ви робите. Замініть ці продукти на SQLite. У нас було саме те саме, один автор, який би виклав дані на диск і оновив на основі SQL TOC та читацький процес (декілька потоків), який би читав TOC, щоб визначити, які дані слід отримати. Не знаю про SQLite в наші дні, але те, що у нас мало спірності, виявилося головним болем у ...
DXM

... позаду. Я не пам'ятаю всіх подробиць, але я думаю, що коли один процес намагався заблокувати, а не міг, тому що читав інший, то СЛУЧАЄ щось божевільне, як 20-30 секунд. Ми в кінцевому підсумку створили виділений потік, який відповідав за доступ до SQLite, і тоді ми мали і наші процеси, і всі потоки в них, серіалізували свої запити БД до цього потоку. Заднім числом я, певно, не пішов би знову з SQLite.
DXM

1
@DXM дякую за попередження, але після декількох тестів я не зіткнувся ні з чим подібним. Я знаю, що sqlite зазнав капітального ремонту з версією 3, яка була близько 2004 року, тому мені цікаво, чи відноситься ваш негативний досвід до того часу.
bb

1
... самі, а не покладайтеся на схеми блокування SQLite. Я не робив роботу сам, це була ще одна команда, але я тримався в циклі здебільшого, щоб надати зворотній зв'язок і з цікавості. Я також зайшов до Інтернету, зробив кілька незалежних читань та знайшов оригінальну сторінку автора. Прочитавши це, у мене склалося враження, що винахідник SQLite просто ненавидів теми і не бачив, чому хтось ними буде користуватися, тому зламали, як думка, тому що занадто багато людей просили про це.
DXM

Відповіді:


25

Ви шукаєте документацію щодо блокування файлів та сумісність .

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

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

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

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


Дякую за ретельну відповідь, Мартійн! Я декілька сценаріїв, щоб зробити тестування, і, здається, два процеси будуть радісно читати і записувати один екземпляр sqlite одночасно. Я робив одночасні запити для читання та запису, які вистрілювали кожні 1/100-ту секунду, і все ще не отримував винятку із заблокованим db. Як не дивно, єдиний раз, коли я отримав повідомлення про помилку "заблокована база даних", було, коли вручну намагалися (з клієнтом командного рядка sqlite3) видалити кілька рядків, а запити на читання знімалися з мого сценарію на 1/100 секунди секунди. Цікаво, чи pysql автоматично повторює запис після такої помилки.
bb

10

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.