Django:如何锁定行以进行读取?

时间:2018-07-20 00:26:37

标签: django database sqlite locking

我的表包含并发工作人员的“任务”。因此,工作人员应该能够从表中“获取”任务,这意味着自动检查任务是否存在,如果存在,则将其删除。在此原子过程完成之前,应锁定其他工作人员。如何在Django中执行这种锁定?

我正在使用类似以下的代码,但是行未锁定以供读取,两个并发的工作人员都进入事务,找到相同的任务,一个成功地获得了任务,但是第二个获得了OperationalError('database is locked',)

使用SQLite

class Task(models.Model):

    @staticmethod
    def get():
        with transaction.atomic():
            task = Task.objects.select_for_update().filter(...).first()
            if task:
                task.delete()
                return task

        return None

2 个答案:

答案 0 :(得分:1)

SQLite不支持行级锁,部分原因是它是基于文件的数据库:

https://www.sqlite.org/atomiccommit.html

  

读取数据库文件的第一步是获取数据库文件的共享锁。 “共享”锁允许同时从数据库文件读取两个或多个数据库连接。但是共享锁可以防止另一个数据库连接在我们读取数据库文件时将其写入数据库文件。

您最好的选择是切换到生产质量数据库,例如PostgreSQL

  

13.3.2。行级锁

     

除了表级锁外,还有行级锁,下面列出了这些行级锁以及PostgreSQL自动使用它们的上下文。

答案 1 :(得分:0)

因此,我很清楚地使用了可用于生产环境的数据库,但是使用SQLite可以轻松使用Redis.lock():

class Task(models.Model):

    @staticmethod
    def get():

        from redis import StrictRedis
        with StrictRedis().lock("some_lock_id"):

            task = Task.objects.filter(...).first()
            if task:
                task.delete()
                return task

        return None