当 Uwsgi 杀死一个 worker 时创建新内容类型时出错

Error creating new content types when Uwsgi kills a worker

我是 运行 一个带有 uwsgi 的 django 应用程序,我正在观察一个案例 有时,当 uwsgi 杀死它的 worker 并重新生成一个 worker。

Thu Aug  8 11:02:33 2019 - worker 1 killed successfully (pid: 25499)
Thu Aug  8 11:02:33 2019 - Respawned uWSGI worker 1 (new pid: 4192)

然后 django 应用程序收到下一个请求 returns 500 错误,异常:

RuntimeError:创建新内容类型时出错。请确保在尝试单独迁移应用程序之前迁移内容类型。

content_type = ContentType.objects.get_for_model(Coupon)

编辑:

Django 版本:1.8.6 Uwsgi 版本:2.0.12

问题

我检查了多个来源和内容类型代码,找到了这种情况的原因。

错误发生在这一行

content_type = ContentType.objects.get_for_model(Coupon)

这里,get_for_model方法首先从缓存中获取对象。如果失败,则从数据库获取,否则在数据库中创建记录。

在我的例子中,与 DB 的连接中断导致了 OperationalError,对于这个错误,它引发了 RuntimeError 以及问题中提到的错误描述。

在 IntegrityError 或 ProgrammingError 的情况下也可以返回相同的错误。

操作错误 为与数据库操作相关且不一定在程序员控制下的错误引发的异常,例如发生意外断开、数据源名称未找到、事务无法处理、处理过程中发生内存分配错误等。它必须是 DatabaseError 的子类。

完整性错误 当数据库的关系完整性受到影响时引发异常,例如外键检查失败。它必须是 DatabaseError 的子类。

编程错误 因编程错误引发的异常,例如table 未找到或已存在,SQL 语句中的语法错误,指定的参数数量错误等。它必须是 DatabaseError 的子类。

来自 Django 1.8.6 源代码的片段:

def get_for_model(self, model, for_concrete_model=True):
    """
    Returns the ContentType object for a given model, creating the
    ContentType if necessary. Lookups are cached so that subsequent lookups
    for the same model don't hit the database.
    """
    opts = self._get_opts(model, for_concrete_model)
    try:
        return self._get_from_cache(opts)
    except KeyError:
        pass

    # The ContentType entry was not found in the cache, therefore we
    # proceed to load or create it.
    try:
        try:
            # We start with get() and not get_or_create() in order to use
            # the db_for_read (see #20401).
            ct = self.get(app_label=opts.app_label, model=opts.model_name)
        except self.model.DoesNotExist:
            # Not found in the database; we proceed to create it.  This time we
            # use get_or_create to take care of any race conditions.
            ct, created = self.get_or_create(
                app_label=opts.app_label,
                model=opts.model_name,
            )
    except (OperationalError, ProgrammingError, IntegrityError):
        # It's possible to migrate a single app before contenttypes,
        # as it's not a required initial dependency (it's contrib!)
        # Have a nice error for this.
        raise RuntimeError(
            "Error creating new content types. Please make sure contenttypes "
            "is migrated before trying to migrate apps individually."
        )
    self._add_to_cache(self.db, ct)
    return ct

解决方案

我需要将我的Uwsgi升级到2.0.14或以上版本之前,Uwsgi杀死任何老工人只给廉价工人