dan*_*ana 48 python database sqlite django locked
我在我的应用程序中进行了一些重复操作(测试它),突然间我得到一个奇怪的错误:
OperationalError: database is locked
Run Code Online (Sandbox Code Playgroud)
我重新启动了服务器,但错误仍然存在.一切都是关于什么的?
pat*_*ick 66
来自django doc:
SQLite意味着是一个轻量级数据库,因此不能支持高级别的并发性.OperationalError:数据库已锁定错误表示您的应用程序正在经历比sqlite在默认配置中可以处理的更多并发性.此错误意味着一个线程或进程对数据库连接具有独占锁定,另一个线程超时等待释放锁定.
Python的SQLite包装器有一个默认的超时值,它确定第二个线程在超时之前允许等待锁的时间长度并引发OperationalError:数据库被锁定错误.
如果您收到此错误,可以通过以下方式解决:
切换到另一个数据库后端.在某个时刻,SQLite对于真实世界的应用程序来说太"精简"了,而这些并发错误表明你已经达到了这一点.
重写代码以减少并发性并确保数据库事务是短暂的.
通过设置timeout database选项optionoption来增加默认超时值
http://docs.djangoproject.com/en/dev/ref/databases/#database-is-locked-errorsoption
Wit*_*ail 27
实际的原因通常是python或django shell已经向DB打开了一个请求并且没有正确关闭; 杀死你的终端访问通常会释放它.我今天在运行命令行测试时遇到此错误.
编辑:我定期对此进行投票.如果您想在不重新启动终端的情况下终止访问,那么从命令行可以执行以下操作:
from django import db
db.connections.close_all()
Run Code Online (Sandbox Code Playgroud)
Ami*_*ini 18
在我的情况下,这是因为我从SQLite浏览器打开数据库.当我从浏览器关闭它时,问题就消失了.
Bas*_*asj 13
我不同意@Patrick的回答,该回答通过引用此文档,将OP的问题(Database is locked)隐式链接到此:
切换到另一个数据库后端。在某些时候,SQLite对于实际的应用程序来说太“精简”了,而这些并发错误表明您已经达到了这一点。
将此问题归咎于SQlite有点“太容易”(正确使用时功能非常强大;它不仅是小型数据库的玩具,而且很有趣:)An SQLite database is limited in size to 140 terabytes。
除非您有一个非常繁忙的服务器同时具有成千上万的连接,否则此Database is locked错误的原因可能是API的错误使用,而不是SQlite固有的问题“太轻”。这里是有关SQLite实现限制的更多信息。
现在的解决方案:
当我同时使用两个脚本使用同一数据库时,我遇到了相同的问题:
解决方案:始终在执行cursor.close()(甚至是只读)查询后尽快执行。
正如其他人所说,还有另一个进程正在使用 SQLite 文件并且尚未关闭连接。如果您使用的是 Linux,您可以db.sqlite3使用以下fuser命令查看哪些进程正在使用该文件(例如):
$ sudo fuser -v db.sqlite3
USER PID ACCESS COMMAND
/path/to/db.sqlite3:
user 955 F.... apache2
Run Code Online (Sandbox Code Playgroud)
如果要停止进程以释放锁,请使用fuser -kwhich 将KILL信号发送到访问该文件的所有进程:
sudo fuser -k db.sqlite3
Run Code Online (Sandbox Code Playgroud)
请注意,这很危险,因为它可能会停止生产服务器中的 Web 服务器进程。
感谢@cz-game 指出fuser!
我在帕特里克的答案中链接的帮助信息未(明确)解决的情况下遇到了此错误消息。
当我过去常常从两个不同的线程transaction.atomic()包装调用FooModel.objects.get_or_create()并同时调用该代码时,只有一个线程会成功,而另一个线程会收到“数据库已锁定”错误。更改超时数据库选项对行为没有影响。
我认为这是因为 sqlite无法处理多个并发写入器,因此应用程序必须自行序列化写入。
threading.RLock我通过使用对象而不是transaction.atomic()当我的 Django 应用程序与 sqlite 后端运行时解决了这个问题。这并不完全等效,因此您可能需要在应用程序中执行其他操作。
这是我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())
Run Code Online (Sandbox Code Playgroud)
当使用 WSL (\\wsl$ ...) 下保存的数据库文件并运行 Windows python 解释器时,我收到此错误。
您可以不将数据库保存在 WSL 树中,也可以在发行版中使用基于 Linux 的解释器。
我在 Flask 应用程序中遇到了这个问题,因为我在 SQLite 浏览器中打开数据库并忘记写入更改。
如果您还在 SQLite 浏览器中进行了任何更改,那么单击“写入更改”,一切都会好起来的。
| 归档时间: |
|
| 查看次数: |
65628 次 |
| 最近记录: |