Форум сайта python.su
0
Добрый всем вечер, не могу решить задачу и найти на неё ответа, возможно кто-то сможет мне в этом помочь, вопрос следующий:
возможно ли в созданной базе данных с помощью модуля shelve вносить изменения одновременно из двух программ; то есть может возникнуть момент, когда запрос на открытие этой БД произойдёт в одно и то же время в обоих программах и тогда возникает ошибка, как её можно избежать?
Офлайн
39
shelve это не совсем база данных. Смотрите в сторону SQL баз данных. Для начала рекомендуется использовать sqlite. Она идет в комплекте с питоном и очень легковесная. Сразу рациональным можно считать изучения ORM. Рекомендую sqlalchemy.
Офлайн
3
Ну а по сути вопроса - одновременно НЕТ (ни одна БД не даст одновременно, ибо это бред), а по очереди да… Перед открытием базы из программы создавай файл на диске (любой, лишь бы был), так линуксы поступают… закончил - удаляй. Из другой проги тоже самое. Соответственно обе проги ждут пока файла не станет…
А sqlite, те же грабли, разве что SQL поддерживает. Один фиг файловая и однопоточная. MySQL например или другая серверная БД в этом проще, но все равно по очереди. Разве что они, серверные, многое с доступом автоматически рулят.
Отредактировано Iskatel (Авг. 24, 2015 02:01:05)
Офлайн
0
А если не переходить на mySQL, можно как-то перед использованием файла с БД проверить его состояние: открыт он уже другой программой или нет? Чтобы подобие очереди создать… Или совет с созданием файла это как раз единствееный выход для этой проверки? В любом случае, уже спасибо за идею!
Офлайн
568
По-моему, вам тут глупости говорят. 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
(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)
Офлайн
3
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()
Офлайн
568
Ну это если хочется назло бабушке уши отморозить. Я тебе и в оракле таблицу намертво заблокирую.
А если нужно нормально работать, не городите длинных транзакций.
Офлайн
3
FishHook
Ну это если хочется назло бабушке уши отморозить. Я тебе и в оракле таблицу намертво заблокирую.
А если нужно нормально работать, не городите длинных транзакций.
Офлайн
3
AngelFrei
то есть может возникнуть момент, когда запрос на открытие этой БД произойдёт в одно и то же время в обоих программах и тогда возникает ошибка, как её можно избежать?
Офлайн
568
Iskatel
А если встретятся - краш
sqlite.connect("database.sql", timeout=30000.0)
Офлайн