首页 > 解决方案 > 在 Huey 中使用线程管理共享资源

问题描述

我必须更新 peewee 数据库()中的许多行(每行增加一个值SqliteDatabase)。有些对象可以不创建,所以我必须在使用它们之前使用默认值创建它们。我会使用 peewee 文档(原子更新)中的方法,但我不知道如何混合model.get_or_create()in [my_array].

所以我决定在事务中进行查询以在最后提交一次(我希望这样做)。

为什么我写堆栈溢出是因为我不知道如何db.atomic()在 Huey 中使用线程(我用 4 个工人测试过),因为.atomic()锁定了连接(peewee.OperationalError: database is locked)。我试过使用@huey.lock_task,但它不是我发现的问题的解决方案。

我班的代码:

class Article(Model):
    name = CharField()
    mention_number = IntegerField(default=0)

    class Meta:
        database = db

我的任务代码:

@huey.task(priority=30)
def update(names):  # "names" is a list of strings
    with db.atomic():
        for name in names:
            article, success = Article.get_or_create(name=name)
            article.mention_number += 1
            article.save()

标签: thread-safetypeeweepython-huey

解决方案


好吧,如果您使用的是最新版本的 Sqlite(3.24 或更高版本),您可以使用 Postgres 样式的 upsert 查询。Peewee 很好地支持这一点:http: //docs.peewee-orm.com/en/latest/peewee/api.html#Insert.on_conflict

要回答有关共享资源的另一个问题,从您的示例中不清楚您希望发生什么...... Sqlite 一次只允许一个写入事务。因此,如果您正在运行多个线程,那么在任何给定时间可能只有其中一个正在写入。

Peewee 将数据库连接存储在本地线程中,因此 Peewee 数据库可以安全地用于多线程应用程序中。

您没有提到为什么 huey lock_task 不起作用。

另一个建议是尝试将 WAL 模式与 Sqlite 一起使用,因为 WAL 模式允许多个读取器事务与单个写入器共存。


推荐阅读