Несколько недель назад я опубликовал этот вопрос на SO относительно того, как заблокировать базу данных sqlite3 в python:
Как заблокировать базу данных sqlite3 в Python?
Однако я не совсем уверен, что ответ работает. Или, может быть, я просто неправильно понимаю ответ.
Вот ситуация, с которой я столкнулся:
- У меня есть база данных "test"
- В базе данных "test" есть одна таблица "book"
- В таблице "book" есть два столбца: "title" и "checked_out_by"
Тогда у меня есть функция, которая работает так:
def checkout(title, user):
con = get_connection_from_db()
with con:
checked_out_by = get_checked_out_by(title)
if checked_out_by == '': # If NOT checked out:
checkout(title, user)
print user, "checked out", title
elif checked_out_by == 'user':
print user, "already got it"
else:
print user, "can't check it out because", checked_out_by, "has it!"
Таким образом, функция checkout () сначала проверяет, что книга НЕ извлечена, и, если это так, проверяет книгу. Обратите внимание, что я использую рекомендованный трюк "с con:", чтобы гарантировать, что все будет транзакционным, счастливым и копацетным.
Однако я запустил несколько тестов параллелизма и обнаружил проблемы. В частности, когда я запускаю два следующих вызова одновременно:
checkout('foo', 'steve')
checkout('foo', 'tim')
Вывод показывает, что он работает не совсем правильно. Я ожидаю увидеть один из двух следующих возможных выводов:
steve checked out foo
tim can't check it out because steve has it!
OR
tim checked out foo
steve can't check it out because tim has it!
Но иногда я получаю такой вывод:
tim checked out foo
steve checked out foo
Я думал, что трюк 'with con:' обеспечит связывание моих вызовов в БД. Может ли кто-нибудь объяснить мне, если / как я понял это неправильно? Если так, есть ли способ заставить это работать?