操作错误:数据库被锁定

2025-03-18 08:56:00
admin
原创
58
摘要:问题描述:我在我的应用程序中进行了一些重复操作(测试它),突然出现了一个奇怪的错误:OperationalError: database is locked 我重启了服务器,但错误仍然存​​在。这是什么原因?解决方案 1:来自Django的文档:SQLite 旨在成为轻量级数据库,因此无法支持高并发水平。Op...

问题描述:

我在我的应用程序中进行了一些重复操作(测试它),突然出现了一个奇怪的错误:

OperationalError: database is locked

我重启了服务器,但错误仍然存​​在。这是什么原因?


解决方案 1:

来自Django的文档:

SQLite 旨在成为轻量级数据库,因此无法支持高并发水平。OperationalError: database is locked错误表明您的应用程序遇到的并发量超出了sqlite默认配置的处理能力。此错误意味着一个线程或进程对数据库连接拥有独占锁,而另一个线程在等待释放锁时超时。

Python 的 SQLite 包装器有一个默认超时值,该值决定了第二个线程在超时并引发错误之前可以在锁上等待多长时间OperationalError: database is locked

如果您收到此错误,可以通过以下方式解决:

  • 切换到另一个数据库后端。在某个时候,SQLite 对于实际应用程序来说变得太“精简”,这些并发错误表明您已经到达了那个点。

  • 重写代码以减少并发性并确保数据库事务是短暂的。

  • 通过设置数据库选项来增加默认超时值timeout

"OPTIONS": {
    # ...
    "timeout": 20,
    # ...
}

这将使 SQLite 等待更长时间才抛出“数据库已锁定”错误;它实际上不会采取任何措施来解决这些问题。

解决方案 2:

我稍微不同意接受的答案,该答案通过引用该文档,隐式地将 OP 的问题 ( Database is locked) 与此联系起来:

切换到另一个数据库后端。在某个时候,SQLite 对于实际应用程序来说变得太“精简”,这些并发错误表明您已经到达了那个点。

将此问题归咎于 SQlite 有点“太容易了”(如果正确使用,它非常强大;它不仅是小型数据库的玩具,有趣的事实An SQLite database is limited in size to 140 terabytes :)。

除非您的服务器非常繁忙,同时有数千个连接,否则此错误的原因Database is locked可能更多是 API 的错误使用,而不是 SQlite 固有的“太轻”问题。以下是有关SQLite 实现限制的更多信息。


现在解决方案:

当我同时使用两个使用同一个数据库的脚本时遇到了同样的问题:

  • 一个是使用写操作访问数据库

  • 另一个是以只读方式访问数据库

解决方案:在完成(即使是只读)查询后始终尽快执行。cursor.close()

以下是更多详细信息。

解决方案 3:

就我而言,这是因为我从SQLite 的数据库浏览器打开了数据库。当我从浏览器关闭它时,问题就消失了。

解决方案 4:

造成这种情况的实际原因通常是 python 或 django shell 已打开对数据库的请求,但未正确关闭;终止终端访问通常可以释放它。我今天在运行命令行测试时遇到了这个错误。

编辑:我定期收到对此的点赞。如果您想在不重新启动终端的情况下终止访问,那么您可以从命令行执行以下操作:

from django import db
db.connections.close_all()

解决方案 5:

我遇到了这个错误信息,但 Patrick 的答案中链接的帮助信息没有(明确)解决这个问题。

当我包装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())

解决方案 6:

正如其他人所说,还有另一个进程正在使用 SQLite 文件并且尚未关闭连接。如果您使用的是 Linux,则可以使用以下命令查看哪些进程正在使用该文件(例如db.sqlite3) :fuser

$ 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

请注意,这很危险,因为它可能会停止生产服务器中的 Web 服务器进程。

感谢@cz-game的指出fuser

解决方案 7:

当我使用在 WSL(\\wsl$...)下保存的数据库文件并运行 Windows Python 解释器时出现此错误。

您既可以不在 WSL 树中保存数据库,也可以在发行版中使用基于 Linux 的解释器。

解决方案 8:

我在我的 flask 应用程序中遇到了这个问题,因为我在 SQLite 浏览器中打开了数据库但忘记写入更改。

如果您也在 SQLite 浏览器中做了任何更改,请单击写入更改,一切都会正常

在此处输入图片描述

解决方案 9:

对我来说,一旦我关闭使用以下方式打开的 django shell,这个问题就会得到解决python manage.py shell

解决方案 10:

如果您通过 pycharm 的 dbbrowser 插件连接到 sqlite db,也可能会发生这种情况。断开连接将解决问题

解决方案 11:

我遇到了同样的错误!原因之一是数据库连接未关闭。因此,请检查未关闭的数据库连接。此外,在关闭连接之前,请检查是否已提交数据库。

解决方案 12:

在第一次实例化 Django (v3.0.3) 之后,我遇到了类似的错误。除了以下情况外,这里的所有建议都不起作用:

  • 删除了db.sqlite3文件并丢失了其中的数据(如果有的话),

  • python manage.py makemigrations

  • python manage.py migrate


顺便说一句,如果您只想测试 PostgreSQL:

docker run --rm --name django-postgres \n  -e POSTGRES_PASSWORD=mypassword \n  -e PGPORT=5432 \n  -e POSTGRES_DB=myproject \n  -p 5432:5432 \n  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

解决方案 13:

检查您的数据库是否在另一个数据库浏览器上打开。

如果它在其他应用程序上打开,则关闭该应用程序并再次运行该程序。

解决方案 14:

只需关闭(停止)并打开(启动)数据库即可。这解决了我的问题。

解决方案 15:

我发现这可以满足我的需要。(线程锁定)YMMV conn = sqlite3.connect(数据库,超时=10)

https://docs.python.org/3/library/sqlite3.html

sqlite3.connect(数据库[,超时,检测类型,隔离级别,检查相同线程,工厂,缓存语句,uri])

当多个连接访问数据库时,如果其中一个进程修改了数据库,则 SQLite 数据库将被锁定,直到提交该事务。超时参数指定连接应等待锁定消失的时间,直到引发异常。超时参数的默认值为 5.0(五秒)。

解决方案 16:

就我而言,我添加了一条手动保存的新记录,并再次通过 shell 尝试添加新记录,这次它完美地运行,请检查一下。

In [7]: from main.models import Flight

In [8]: f = Flight(origin="Florida", destination="Alaska", duration=10)

In [9]: f.save()

In [10]: Flight.objects.all() 
Out[10]: <QuerySet [<Flight: Flight object (1)>, <Flight: Flight object (2)>, <Flight: Flight object (3)>, <Flight: Flight object (4)>]>

解决方案 17:

实际上我也遇到过同样的问题,当我使用“transaction.atomic() with select_for_update()”时,我收到错误消息“OperationalError:数据库已锁定”,

经过多次尝试/搜索/阅读 django 文档后,我发现问题出在 SQLite 本身,它不支持 select_for_update 方法,正如 django DOCs 所说,请查看以下网址并深入阅读:

https://docs.djangoproject.com/en/dev/ref/databases/#database-is-locked-errors

,当我转到 MySQL 时,一切都顺利。

由于 django DOCs 也说当数据库超时时可能会发生“数据库被锁定”,他们建议您通过设置以下选项来更改数据库超时:

'OPTIONS': {
    # ...
    'timeout': 20,
    # ...
}

最后,即使您在开发环境中工作,我建议您使用 MySQL/PostgreSQL。

我希望这对你有帮助。

解决方案 18:

就我的情况而言,我没有保存在 SQLite 浏览器中执行的数据库操作。保存后问题就解决了。

解决方案 19:

这是一个非常不寻常的情况,它发生在我身上。

存在无限递归,不断创建对象。

更具体地说,使用 DRF,我在视图中覆盖了创建方法,并且我做到了

def create(self, request, *args, **kwargs):
    ....
    ....

    return self.create(request, *args, **kwargs)

解决方案 20:

这里已经有很多答案,我甚至想分享我的案例,这可能会对某些人有所帮助。

我已经在 Python API 中打开了连接来更新值,只有在收到服务器响应后才会关闭连接。这里我所做的是,在关闭 Python API 中的连接之前,我已经打开了连接以在服务器中执行其他操作。

解决方案 21:

如果您在使用时收到此错误manage.py shell,则可能的原因之一是您正在运行的开发服务器 ( manage.py runserver) 正在锁定数据库。使用 shell 时停止服务器总能解决问题。

解决方案 22:

当我尝试在 SQLite 中创建一个新表但session对象包含未提交的(虽然已刷新)更改时出现此错误。

请确保:

  1. 在创建新表之前提交会话

  2. 关闭所有会话并在新连接中执行表创建

  3. ...

解决方案 23:

@Shilp Thapak的回答是正确的:错误的原因是您在运行应用程序之前没有将手动更改写入 SQLite 数据库浏览器中的数据。

如果你没有在你使用的 SQL 客户端中写入更改,你仍然可以创建引擎,但是

engine.connect()

运行代码片段Hide results展开片段

将抛出有关数据库被锁定的操作错误。

您可以通过检查回滚日志是否存在来检查您的引擎是否可以连接。回滚日志的默认模式是在事务开始和结束时创建和删除。

它存在于数据库所在的同一目录中,与数据库文件具有相同的名称并附加后缀“-journal”。

如果模式没有改变,则在 SQLite 的 DB 浏览器中的编辑编译指示面板中的日志模式下。

您可以像这样检查临时文件是否存在:

if os.path.isfile('your-database.sqlite-journal'):
    print("The database is locked. Please write your changes in your SQL client before proceeding.
")

运行代码片段Hide results展开片段

在这里阅读有关临时文件的更多信息。

因此无需为此关闭 SQLite 的服务器或数据库浏览器。事实上,只要写入所有更改,您就可以让多个客户端同时连接到数据库,并且仍可同时运行您的应用程序。

解决方案 24:

对于我来说,我尝试使用 gunicorn 将数据库部署到主机,并且我只使用了一个工作程序,因此数据库被锁定。添加到 gunicorn_config.py

工人=3

解决方案 25:

我在服务生产 DJANGO 服务器上遇到了同样的问题。我们通过使用 DB 工具(例如“DB Browser”)缩小 sqlite DB 来解决问题。

解决方案 26:

我的解决方案是,我忘记在执行查询后使用 conn.commit()。

解决方案 27:

当我从 Excel 文件向表中插入值时,出现了错误。我执行此操作时打开了我的 Excel 文件。关闭 Excel 文件后,一切正常。所以也许可以检查是否有其他程序访问过您的文件。我想这可以帮助处于类似情况的其他人。

解决方案 28:

我刚刚解决了很难找到支持 WAL(预写日志)的记录标志的问题。

这是其他数据库中相当标准和默认的,并且提供了更好的并发性,请readers do not block writers and a writer does not block readers. Reading and writing can proceed concurrently.参阅https://www.sqlite.org/wal.html

因此只需确保通过执行以下操作来更改 journal_mode:

PRAGMA journal_mode=WAL

解决方案 29:

更新django 版本 2.1.7

sqlite3.OperationalError: database is locked在使用pytestwith时遇到此错误django

解决方案:

如果我们使用@pytest.mark.django_db装饰器。它的作用是创建一个in-memory-db用于测试的。

命名:file:memorydb_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 ... == ....

解决方案 30:

我只需要添加alias sqlite='sqlite3'到我的~/.zshrc

然后我删除了部分失败的创建并重新运行virtualenv,它运行得很顺利~/.pyenv/versions/new-virtualenv`pyenv virtualenv <name>`

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2379  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1510  
  PLM(产品生命周期管理)系统在企业项目管理中扮演着至关重要的角色,它能够整合产品从概念设计到退役的全流程信息,提升协同效率,降低成本。然而,项目范围蔓延是项目管理过程中常见且棘手的问题,在PLM系统环境下也不例外。范围蔓延可能导致项目进度延迟、成本超支、质量下降等一系列不良后果,严重影响项目的成功交付。因此,如何在P...
plm项目经理是做什么   16  
  PLM(产品生命周期管理)系统在现代企业的产品研发与管理过程中扮演着至关重要的角色。它不仅仅是一个管理产品数据的工具,更能在利益相关者分析以及沟通矩阵设计方面提供强大的支持。通过合理运用PLM系统,企业能够更好地识别、理解和管理与产品相关的各类利益相关者,构建高效的沟通机制,从而提升产品开发的效率与质量,增强企业的市场...
plm是什么   20  
  PLM(产品生命周期管理)项目管理对于企业产品的全生命周期规划、执行与监控至关重要。在项目推进过程中,监控进度偏差是确保项目按时、按质量完成的关键环节。五维健康检查指标体系为有效监控PLM项目进度偏差提供了全面且系统的方法,涵盖了项目的多个关键维度,有助于及时发现问题并采取针对性措施。需求维度:精准把握项目基石需求维度...
plm项目管理软件   18  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用