操作错误: 游标"_django_curs_<id>"不存在。

23
我们有一个在线商店网页应用程序,由Django、PostgreSQL和Heroku驱动。
针对某项特定活动(可以将其视为要购买的产品),我们已经成功出售了10K+份副本。然而,根据我们Sentry报告的内容,一些用户遇到了错误。这些用户的常见规格是:在购买之前没有地址信息。通常,用户在注册后会立即填写地址表单。如果他们没有填写,则需要在购买产品时填写表单并一起提交。
这就是跟踪的样子:
OperationalError: cursor "_django_curs_140398688327424_146" does not exist

(66 additional frame(s) were not displayed)
...
  File "store/apps/store_main/templatetags/store_form_filters.py", line 31, in render_form
    return render_to_string('widgets/store_form_renderer.html', ctx)
  File "store/apps/store_main/templatetags/store_form_filters.py", line 20, in render_widget
    return render_to_string('widgets/store_widget_renderer.html', ctx)
  File "store/apps/store_main/widgets.py", line 40, in render
    attrs=attrs) + "<span class='js-select-support select-arrow'></span><div class='js-select-support select-arrow-space'><b></b></div>"

OperationalError: cursor "_django_curs_140398688327424_146" does not exist 

还有一个奇怪的共同点,就是在 SQL 查询失败之前会出现异常消息。您可以在下面的图片中看到:

Exception while resolving variable

如果它们以某种方式相关,我就添加它们。可能相关的另一件事是,在批量邮件之后立即尝试购买活动的用户会遇到此错误。因此,可能原因是大量流量,但我们也不确定。

由于 Heroku 托管 postgres,我们向他们询问问题,但他们也没有任何线索。

我知道这个错误的正式原因是在提交后尝试访问游标。由于事务后被销毁,尝试访问会导致此错误,但我在我们的场景中没有看到这一点。我们没有以任何方式触碰游标。我漏掉了什么?可能会导致这个错误?如何防止它?任何想法将不胜感激。


这里有些感觉像缓存。您能分享一下您的生产环境的更多细节吗? - souldeux
4个回答

34

在我的情况下,我忘记将新应用程序添加到 settings.py 文件中并进行迁移。出于习惯,我只执行了迁移操作,这当然不包括新应用程序的模型。 - artifex_knowledge
谢谢!这是一个类似错误的原因:_'CommandError: 无法序列化数据库:游标"_django_curs_281473738641440_sync_1"不存在'_。 - undefined

7
如果您正在使用 django-pytest,并且已启用优化参数 --reuse-db,并在测试运行之间进行了数据库迁移,则需要重新创建数据库表。
pytest --create-db

3

很可能您忘记了进行makemigrations并将其迁移到数据库中。 如果您确定已经进行了迁移并且运行python manage.py makemigrationspython manage.py migrate没有找到您所做的更改,则数据库和模型不同步。 有时,如果您有一个大型数据库,这种情况可能非常令人沮丧。您需要手动检查您的模型。

为了帮助您,您可以尝试这个技巧,这对我很有效。

  • 步骤1(删除应用程序中的所有迁移) 我假设您正在使用Unix终端。运行sudo rm -rv */migrations/*。这将删除所有迁移文件和缓存。
  • 步骤2(在每个应用程序中创建迁移文件夹) 运行命令mkdir <app-folder>/migrations && touch <app-folder>/__init__.py。用您默认的Django设置文件中的INSTALLED_APPS列表中的应用程序名称替换。
  • 步骤3(制作迁移) 在此步骤中,我们使用迁移文件填充每个应用程序中的迁移文件夹。运行python manage.py makemigrations命令。运行第二个命令。python manage.py migrate --fake。我们使用--fake标志是因为数据已经存在于数据库中,所以我们不想填充已经存在的数据库表,否则您将会看到“已存在错误”。
如果这个方法不起作用,那么你需要在数据库中调整一些额外的字段,比如django_migrations或者类似命名的表。但是这并不推荐,因为还有其他依赖于它的数据库表,比如django_contenttypes,这会让你陷入一连串相关表的困境,需要手动检查,非常痛苦。
所以,如果你想直接操作数据库,这里有另一个技巧。首先,你需要有正确的权限以用户身份编辑数据库。如果你使用的是sqlite3作为数据库,你可以使用类似sqlite工具的工具。
好了,一旦进入你用于Django项目的数据库,寻找一个名为"django_migrations"的关系或表。删除这个表。通常情况下,由于外键约束,删除会失败,所以要删除与django_migrations表相关的每个数据库关系/表。这些表包括django_contenttypes、auth_permissions(以及我可能遗漏的其他表)。 不用担心,因为你不会对重要的实际Web应用程序数据进行操作。删除后,在活动的虚拟环境中运行迁移命令"python manage.py makemigrations"和"python manage.py migrate"。
这样很可能会解决这个错误。

0
我遇到了同样的问题,并通过分析回溯发现它与迁移无关。
Traceback (most recent call last):
  File "/opt/venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/venv/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1560, in execute_sql
    cursor.execute(sql, params)
  File "/opt/venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/opt/venv/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/opt/venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
django.db.utils.OperationalError: temporary file size exceeds temp_file_limit (1537530kB)
ERROR:  temporary file size exceeds temp_file_limit (1537530kB)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
psycopg2.errors.ConfigurationLimitExceeded:  (1537530kB)

造成失败的原因是Postgres配置temp_file_limit,这使得无法创建游标,因为它

限制每个进程使用的所有临时文件的总大小 指定进程可以用于临时文件(如排序和哈希临时文件或已保持游标的存储文件)的最大磁盘空间。试图超过此限制的事务将被取消。如果未指定单位,则以千字节为准。-1(默认值)表示无限制。只有超级用户和具有适当SET特权的用户才能更改此设置。

而另一个错误发生在尝试处理此异常时。



During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/manage.py", line 20, in <module>
    main()
  File "/usr/src/app/manage.py", line 16, in main
    execute_from_command_line(sys.argv)
  File "/opt/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/opt/venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/venv/lib/python3.11/site-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/venv/lib/python3.11/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/lib/python3.11/site-packages/django/core/management/commands/dumpdata.py", line 265, in handle
    serializers.serialize(
  File "/opt/venv/lib/python3.11/site-packages/django/core/serializers/__init__.py", line 134, in serialize
    s.serialize(queryset, **options)
  File "/opt/venv/lib/python3.11/site-packages/django/core/serializers/base.py", line 132, in serialize
    for count, obj in enumerate(queryset, start=1):
  File "/opt/venv/lib/python3.11/site-packages/django/core/management/commands/dumpdata.py", line 222, in get_objects
    yield from queryset.iterator()
  File "/opt/venv/lib/python3.11/site-packages/django/db/models/query.py", line 516, in _iterator
    yield from iterable
  File "/opt/venv/lib/python3.11/site-packages/django/db/models/query.py", line 91, in __iter__
    results = compiler.execute_sql(
              ^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1563, in execute_sql
    cursor.close()
psycopg2.errors.InvalidCursorName: cursor "_django_curs_..._sync_8" does not exist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接