Python 操作错误:数据库已锁定
我在我的应用程序中进行了一些重复操作(测试),突然出现了一个奇怪的错误:Python 操作错误:数据库已锁定,python,django,database,sqlite,locked,Python,Django,Database,Sqlite,Locked,我在我的应用程序中进行了一些重复操作(测试),突然出现了一个奇怪的错误: OperationalError: database is locked 我已重新启动服务器,但错误仍然存在。这是怎么回事?来自django doc: SQLite是轻量级的 数据库,因此无法支持 高水平的并发性。 操作错误:数据库已锁定 错误表明您的应用程序 正在经历比以前更多的并发性 sqlite在默认情况下可以处理 配置这个错误意味着 一个线程或进程具有独占 锁定数据库连接并 另一个线程在等待时超时 锁不能松开 P
OperationalError: database is locked
我已重新启动服务器,但错误仍然存在。这是怎么回事?来自django doc:
SQLite是轻量级的
数据库,因此无法支持
高水平的并发性。
操作错误:数据库已锁定
错误表明您的应用程序
正在经历比以前更多的并发性
sqlite在默认情况下可以处理
配置这个错误意味着
一个线程或进程具有独占
锁定数据库连接并
另一个线程在等待时超时
锁不能松开
Python的SQLite包装器有一个默认值
超时值,用于确定超时时间
允许第二个线程等待
在锁超时和关闭之前打开它
引发错误:数据库
是锁定错误
如果您遇到此错误,您可以
通过以下方式解决此问题:
- 切换到另一个数据库后端。在某一点上,SQLite对于现实世界的应用程序来说变得过于“精简”,而这些并发错误表明您已经达到了这一点
- 重写代码以降低并发性并确保数据库事务是短期的
- 通过设置超时数据库选项增加默认超时值
这种情况的实际原因通常是python或django shell打开了对DB的请求,但没有正确关闭;终止终端访问通常会释放它。我今天在运行命令行测试时出现了这个错误 编辑:我得到定期的投票。如果希望在不重新启动终端的情况下终止访问,则可以从命令行执行以下操作:
from django import db
db.connections.close_all()
在我的例子中,这是因为我从SQLite浏览器打开了数据库。当我从浏览器关闭它时,问题就消失了。请尝试以下命令:
sudo fuser -k 8000/tcp
在我的例子中,我没有保存在SQLite浏览器中执行的数据库操作。保存它解决了问题。我不同意@Patrick的回答,他引用了这篇文档,暗示OP的问题(
数据库被锁定
)与此相关:
切换到另一个数据库后端。在某一点上,SQLite对于现实世界的应用程序来说变得过于“精简”,而这些并发错误表明您已经达到了这一点
这有点“太容易”将SQlite归咎于这个问题(如果正确使用,它不仅是小型数据库的玩具,有趣的事实是:SQlite数据库的大小限制为140 TB
)
除非您的服务器非常繁忙,同时有数千个连接,此数据库被锁定的原因可能更多地是API使用不当,而不是SQlite固有的问题,即“太轻”
。这里有更多的信息
现在,解决方案是: 当我同时使用同一数据库的两个脚本时,我遇到了同样的问题:
- 一个是通过写操作访问数据库
- 另一个正在以只读方式访问数据库
cursor.close()
。
.如果您通过pycharm通过dbbrowser插件连接到sqlite db,也可能发生这种情况。断开连接将解决问题对我来说,一旦我关闭了django shell,它就会得到解决,django shell是使用
python manage.py shell打开的
更新django版本2.1.7
我得到了这个错误sqlite3.OperationalError:数据库被锁定
使用pytest
和django
解决方案:
如果我们使用的是@pytest.mark.django_db
装饰器。它所做的是在内存db中创建一个用于测试的
命名:file:memorydb\u default?mode=memory&cache=shared
我们可以通过以下方式获得此名称:
from django.db import connection
db_path = connection.settings_dict['NAME']
要访问并编辑此数据库,请执行以下操作:
连接到数据库:
with sqlite3.connect(db_path, uri=True) as conn:
c = conn.cursor()
使用uri=True
指定作为要打开的SQLite数据库的磁盘文件
要避免此错误,请在装饰器中激活事务:
@pytest.mark.django_db(transaction=True)
最终功能:
from django.db import connection
@pytest.mark.django_db(transaction=True)
def test_mytest():
db_path = connection.settings_dict['NAME']
with sqlite3.connect(db_path, uri=True) as conn:
c = conn.cursor()
c.execute('my amazing query')
conn.commit()
assert ... == ....
正如其他人所说,还有另一个进程正在使用SQLite文件,但尚未关闭连接。如果您使用的是Linux,则可以使用fuser
命令查看哪些进程正在使用该文件(例如db.sqlite3
),如下所示:
$sudo fuser-v db.sqlite3
用户PID访问命令
/路径/to/db.sqlite3:
用户955F。。。。apache2
如果要停止进程以释放锁,请使用fuser-k
,它会向访问文件的所有进程发送KILL
信号:
sudo fuser-k db.sqlite3
请注意,这是危险的,因为它可能会停止生产服务器中的web服务器进程
感谢@cz game指出fuser 我也犯了同样的错误!原因之一是数据库连接未关闭。
因此,请检查是否有未关闭的数据库连接。另外,在关闭连接之前,请检查您是否提交了数据库。我在patrick回答中链接的帮助信息没有(清楚)说明的情况下遇到了此错误消息 当我使用
transaction.atomic()
包装对FooModel.objects.get\u或\u create()
的调用,并从两个不同的线程同时调用该代码时,只有一个线程会成功,而另一个线程会出现“database is locked”错误。更改超时数据库选项对行为没有影响
我认为这是由于sqlite的存在,因此应用程序必须自己序列化写操作
我用th解决了这个问题
pip install psycopg2-binary
python manage.py makemigrations
python manage.py migrate
def create(self, request, *args, **kwargs):
....
....
return self.create(request, *args, **kwargs)
'OPTIONS': {
# ...
'timeout': 20,
# ...
}