A few weeks ago, I posted this question on SO regarding how to lock a sqlite3 database in python:
How to lock a sqlite3 database in Python?
However, I'm not quite convinced that the answer works. Or, maybe I'm just misunderstanding the answer.
Here's the situation I ran into:
- I've got a database "test"
- In database "test" there is one table "book"
- In table "book" there are two columns: "title", and "checked_out_by"
Then I have a function that works like this:
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!"
So the checkout() function first verifies that the book is NOT checked out, and, if so, checks out the book. Note that I'm using the recommended "with con:" trick to ensure that everything is transactional and happy and copacetic.
However, I ran a bunch of concurrency tests and found problems. Specifically, when I run the two following calls concurrently:
checkout('foo', 'steve')
checkout('foo', 'tim')
The output indicates that it doesn't work quite right. I expect to see one of the two following possible outputs:
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!
But occasionally, I'll get this output:
tim checked out foo
steve checked out foo
I thought the 'with con:' trick would ensure that my DB calls would be bundled together. Can someone explain to me if/how I got this wrong? If so, is there a way to make this work?
See Question&Answers more detail:
os