Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 23, 2015 22:40:09

AngelFrei
Зарегистрирован: 2015-08-23
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

Добрый всем вечер, не могу решить задачу и найти на неё ответа, возможно кто-то сможет мне в этом помочь, вопрос следующий:
возможно ли в созданной базе данных с помощью модуля shelve вносить изменения одновременно из двух программ; то есть может возникнуть момент, когда запрос на открытие этой БД произойдёт в одно и то же время в обоих программах и тогда возникает ошибка, как её можно избежать?

Офлайн

#2 Авг. 23, 2015 22:57:14

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

shelve это не совсем база данных. Смотрите в сторону SQL баз данных. Для начала рекомендуется использовать sqlite. Она идет в комплекте с питоном и очень легковесная. Сразу рациональным можно считать изучения ORM. Рекомендую sqlalchemy.

Офлайн

#3 Авг. 24, 2015 02:00:43

Iskatel
Зарегистрирован: 2015-07-29
Сообщения: 291
Репутация: +  3  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

Ну а по сути вопроса - одновременно НЕТ (ни одна БД не даст одновременно, ибо это бред), а по очереди да… Перед открытием базы из программы создавай файл на диске (любой, лишь бы был), так линуксы поступают… закончил - удаляй. Из другой проги тоже самое. Соответственно обе проги ждут пока файла не станет…

А sqlite, те же грабли, разве что SQL поддерживает. Один фиг файловая и однопоточная. MySQL например или другая серверная БД в этом проще, но все равно по очереди. Разве что они, серверные, многое с доступом автоматически рулят.

Отредактировано Iskatel (Авг. 24, 2015 02:01:05)

Офлайн

#4 Авг. 24, 2015 07:47:21

AngelFrei
Зарегистрирован: 2015-08-23
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

А если не переходить на mySQL, можно как-то перед использованием файла с БД проверить его состояние: открыт он уже другой программой или нет? Чтобы подобие очереди создать… Или совет с созданием файла это как раз единствееный выход для этой проверки? В любом случае, уже спасибо за идею!

Офлайн

#5 Авг. 24, 2015 08:46:41

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

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

#!/usr/bin/env python
# -* coding: utf-8 -*-
import sqlite3
import time
import random
import sys
conn = sqlite3.connect('example.db')
c = conn.cursor()
proccess = sys.argv[1]
for i in range(10):
    c.execute("INSERT INTO test VALUES (?, ?)", ["process %s" % proccess, random.randint(0, 10000)])
    conn.commit()
    time.sleep(random.randint(1, 8))
c.execute("select * from test")
print "result = "
for i in c.fetchall():
    print i
conn.close()

запускаем этот скрипт одновременно в двух разных терминалах, эмулируя одновременную работу двух программ,
python test_insert.py 1
python test_insert.py 2
получаем 20 вставок в БД

(u'process 1', 3787.0)
(u'process 1', 6370.0)
(u'process 2', 2569.0)
(u'process 2', 6926.0)
(u'process 1', 5498.0)
(u'process 2', 275.0)
(u'process 1', 2108.0)
(u'process 1', 4542.0)
(u'process 2', 3892.0)
(u'process 1', 3357.0)
(u'process 2', 6789.0)
(u'process 2', 3863.0)
(u'process 1', 9464.0)
(u'process 2', 2749.0)
(u'process 1', 1060.0)
(u'process 1', 3435.0)
(u'process 1', 9713.0)
(u'process 2', 7232.0)
(u'process 2', 7931.0)
(u'process 2', 812.0)

Или это не то, что нужно топикстартеру?



Офлайн

#6 Авг. 24, 2015 09:31:47

Iskatel
Зарегистрирован: 2015-07-29
Сообщения: 291
Репутация: +  3  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

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

сделай так: в одной консольке подвесь открытое соединение, например так
import sqlite3
import time
conn = sqlite3.connect('example.db')
res = conn.execute("select * from test")
res.fetchone()
time.sleep(100)

а в другой запусти это
import sqlite3
conn = sqlite3.connect('example.db')
conn.execute("INSERT INTO test VALUES (?, ?)", ['test', 1])
conn.commit()

у меня (второй питон) стабильно

Traceback (most recent call last):
File "D:\ !\untitled136.py", line 15, in <module>
conn.commit()
sqlite3.OperationalError: database is locked

Офлайн

#7 Авг. 24, 2015 10:16:33

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

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



Офлайн

#8 Авг. 24, 2015 11:11:31

Iskatel
Зарегистрирован: 2015-07-29
Сообщения: 291
Репутация: +  3  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

FishHook
Ну это если хочется назло бабушке уши отморозить. Я тебе и в оракле таблицу намертво заблокирую.
А если нужно нормально работать, не городите длинных транзакций.

Намертво это для примера. Вот ваш пример работает только потому, что вставки успевают “проскочить” между друг другом. А если встретятся - краш. Оно конечно будет работать, до какогото вошебного момента, может вообще всю жизнь не упадет. Но знать о проблеме и оставлять бомбу в программе ИМХО не стоит.

Офлайн

#9 Авг. 24, 2015 11:26:30

Iskatel
Зарегистрирован: 2015-07-29
Сообщения: 291
Репутация: +  3  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

AngelFrei
то есть может возникнуть момент, когда запрос на открытие этой БД произойдёт в одно и то же время в обоих программах и тогда возникает ошибка, как её можно избежать?

Я сумбурно написал - попробую подробней.
перед тем как полезть в базу, проверь нет ли на диске файла с именем “не лезь в базу”.

1. если нет, создай такой, работай с базой, удали файл.
2. если есть, жди полсекунды и снова пробуй.
В другой программе тоже самое.

Соответственно файл живет всего долю секунды (или сколько там вставка происходит)

Стандартное решение таких задач…

Офлайн

#10 Авг. 24, 2015 11:33:39

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Работа с одной БД из двух программ

Iskatel
А если встретятся - краш

sqlite.connect("database.sql", timeout=30000.0)
И пусть они себе встречаются



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version