我在应用程序中进行了一些重复操作(测试它),突然出现了一个奇怪的错误:
OperationalError: database is locked
我已经重启了服务器,但错误仍然存在。这可能是什么原因?
在我的情况下,问题是因为我从SQLite浏览器中打开了数据库。当我从浏览器中关闭它时,问题就解决了。
数据库已锁定
)与以下问题相关联:
这有点“过于简单”地指责SQlite造成了这个问题(当正确使用时,它是非常强大的;这不仅仅是一个小型数据库的玩具,有趣的事实是:切换到另一个数据库后端。在某个时候,SQLite对于实际应用程序来说变得太“轻”,而这些并发错误表明您已经达到了这一点。
SQLite数据库大小限制为140TB
)。数据库已锁定
错误的原因可能更多地是API的错误使用,而不是SQlite固有的问题,因为它会变得“太轻”。这里有更多关于SQLite的实现限制的信息。
cursor.close()
。
以下是更多详细信息。
这通常是由于Python或Django shells打开了一个对数据库的请求,但没有正确关闭,关闭终端访问通常可以释放它。今天我在运行命令行测试时遇到了这个错误。
编辑:我经常得到此类点赞。如果您想在不重启终端的情况下关闭访问权限,则可以从命令行执行以下操作:
from django import db
db.connections.close_all()
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "<subfolder_with_setings.json>.settings")
否则,在我看来,这是最佳答案。 - Oliver Zendeldb.connections.close_all()
的提示。我一直在寻找一些能够在 tearDown()
中调用清理脚本之前解锁数据库的方法,这个方法解决了我的问题。谢谢。 - fbicknelfrom django.conf import settings settings.configure()
。 - Foad S. Farimani正如其他人所说,有另一个进程正在使用 SQLite 文件并未关闭连接。如果您正在使用 Linux,则可以使用以下命令 fuser
查看使用文件(例如db.sqlite3
)的进程:
$ sudo fuser -v db.sqlite3
USER PID ACCESS COMMAND
/path/to/db.sqlite3:
user 955 F.... apache2
如果您想停止进程以释放锁定,请使用fuser -k
,该命令向访问文件的所有进程发送KILL
信号:
sudo fuser -k db.sqlite3
sudo fuser -k app.db
。 - Tri我在使用保存在WSL文件树(\\wsl$ ...)下的数据库文件,并在Windows上运行Python解释器时遇到了这个错误。
你可以选择不在WSL-tree中保存数据库,或者在你的Linux分发版中使用基于Linux的解释器。
在一个情况下,我遇到了这个错误信息,但是帮助文档中没有(明确)提到如何解决,这个情况是在使用transaction.atomic()
来包装一个对FooModel.objects.get_or_create()
的调用,并同时从两个不同的线程中调用该代码时,只有一个线程能成功,而另一个则会出现“数据库被锁定”的错误。更改超时数据库选项对行为没有影响。
我认为这是由于sqlite 无法处理多个同时写入者,所以应用程序必须自己序列化写操作。当我的Django应用程序运行在sqlite后端时,我使用了threading.RLock
对象来替换transaction.atomic()
,虽然这并不完全等效,因此您可能需要在您的应用程序中做一些其他的事情。
以下是我同时从两个不同的线程中运行FooModel.objects.get_or_create
的代码,如果有用的话:
from concurrent.futures import ThreadPoolExecutor
import configurations
configurations.setup()
from django.db import transaction
from submissions.models import ExerciseCollectionSubmission
def makeSubmission(user_id):
try:
with transaction.atomic():
e, _ = ExerciseCollectionSubmission.objects.get_or_create(
student_id=user_id, exercise_collection_id=172)
except Exception as e:
return f'failed: {e}'
e.delete()
return 'success'
futures = []
with ThreadPoolExecutor(max_workers=2) as executor:
futures.append(executor.submit(makeSubmission, 296))
futures.append(executor.submit(makeSubmission, 297))
for future in futures:
print(future.result())
对我而言,问题解决的方法是关闭使用 python manage.py shell
命令打开的 Django shell。
我曾经遇到过类似的错误,在第一次实例化Django(v3.0.3)之后。这里所有的建议都没有起作用,除了:
db.sqlite3
文件并丢失其中的数据(如果有的话)python manage.py makemigrations
python manage.py migrate
顺便说一下,如果你只是想测试PostgreSQL:
docker run --rm --name django-postgres \
-e POSTGRES_PASSWORD=mypassword \
-e PGPORT=5432 \
-e POSTGRES_DB=myproject \
-p 5432:5432 \
postgres:9.6.17-alpine
更改settings.py
,添加以下DATABASES
设置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'postgres',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
...并添加数据库适配器:
pip install psycopg2-binary
python manage.py makemigrations
python manage.py migrate
create_engine('sqlite:///{}'.format(xxx), connect_args={'timeout': 15})
- kawing-chiu