I sometimes randomly encounter:
OperationalError: database is locked
in a process that updates a SQLite database, but I find it difficult to reproduce the error:
SELECT
, etc.) here and there, but no committingI've already read OperationalError: database is locked
Question: Is there a way, when this error happens, to log which other process ID is responsible for the lock?
More generally, how to debug a OperationalError: database is locked
?
Normally, the error occurs when two users try to run transactions on the same tables and change the content. SQLite engine finds it abnormal and locks the database. Now, the user cannot run more transactions.
Click Databases > Database Details List (or Database List) Left-click the gray rectangle on the left side of your database name to select the database. Right-click the same gray rectangle and choose Unlock database. Click OK on the confirmation prompt.
Solution: Always close the cursor
for (even read-only) queries!
First, here is a way to reproduce the problem:
First run this code, once:
import sqlite3
conn = sqlite3.connect('anothertest.db')
conn.execute("CREATE TABLE IF NOT EXISTS mytable (id int, description text)")
for i in range(100):
conn.execute("INSERT INTO mytable VALUES(%i, 'hello')" % i)
conn.commit()
to initialize the test.
Then begin a read-only query:
import sqlite3, time
conn = sqlite3.connect('anothertest.db')
c = conn.cursor()
c.execute('SELECT * FROM mytable')
item = c.fetchone()
print(item)
print('Sleeping 60 seconds but the cursor is not closed...')
time.sleep(60)
and keep this script running while executing the next step:
Then try to delete some content and commit:
import sqlite3
conn = sqlite3.connect('anothertest.db')
conn.execute("DELETE FROM mytable WHERE id > 90")
conn.commit()
It will trigger this error indeed:
sqlite3.OperationalError: database is locked
Why? Because it's not possible to delete data that is currently accessed by a read-query: if the cursor it's still open, it means the data could still be fetched with fetchone
or fetchall
.
Here is how to solve the error: in step #2, just add:
item = c.fetchone()
print(item)
c.close()
time.sleep(60)
Then while this is still running, start script #3, you will see there is no more error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With