问题描述
如何处理Django模型中的并发?我不希望记录的更改被另一个读取相同记录的用户覆盖。
一个Django问题。
并发控制通常表现为一个技术问题,但在许多方面是功能需求的问题。你想要/需要你的应用程序工作?直到我们知道,这将是很难给任何Django的具体建议。
但是,我喜欢漫步,所以这里...
在面对需要并发控制时问自己:
- 两个用户需要同时修改同一记录的可能性有多大?
- 如果对记录的修改丢失,对用户的影响是什么?
如果碰撞的可能性相对较高,或者失去修改的影响很严重,的悲观锁定。在悲观方案中,每个用户必须在打开记录以进行修改之前获取逻辑锁。
悲观锁定具有很多复杂性。您必须同步对锁的访问,考虑容错,锁定到期,超级用户可以锁定锁定,用户可以查看谁拥有锁定等。
在Django中,这可以通过单独的Lock模型或锁定记录上的某种锁定用户外键来实现。使用锁定表可以在存储锁定时获得更多的灵活性,用户,注释等。如果你需要一个通用的锁表,可以用来锁定任何类型的记录,那么请看看,但很快这可以移植到抽象宇航员综合征。
如果碰撞是不可能的或丢失的修改被轻易地重新创建,那么你可以在功能上摆脱乐观的并发技术。这种技术简单易行。基本上,您只需跟踪版本号或修改时间戳,并拒绝您检测到的任何修改。
从功能设计的角度来看,您只有考虑如何向用户提供这些并发修改错误。
在Django方面,可以通过覆盖模型类上的save方法来实现乐观并发控制。 。
def save(self,* args,** kwargs):
if self.version! read_current_version():
raise ConcurrentModificationError('Ooops !!!!')
super(MyModel,self).save(* args,** kwargs)
How do I handle concurrency in a Django model? I dont want the changes to the record being overwritten by another user who reads the same record
解决方案The short answer, this really isn't a Django question as presented.
Concurrency control is often presented as a technical question, but is in many ways a question of functional requirements. How do you want/need your application to work? Until we know that, it will be difficult to give any Django-specific advice.
But, I feel like rambling, so here goes...
There are two questions that I tend to ask myself when confronted with the need for concurrency control:
- How likely is it that two users will need to concurrently modify the same record?
- What is the impact to the user if his/her modifications to a record are lost?
If the likelihood of collisions is relatively high, or the impact of losing a modification is severe, then you may be looking at some form of pessimistic locking. In a pessimistic scheme, each user must acquire a logical lock prior to opening the record for modification.
Pessimistic locking comes with much complexity. You must synchronize access to the locks, consider fault tolerance, lock expiration, can locks be overridden by super users, can users see who has the lock, so on and so on.
In Django, this could be implemented with a separate Lock model or some kind of 'lock user' foreign key on the locked record. Using a lock table gives you a bit more flexibility in terms of storing when the lock was acquired, user, notes, etc. If you need a generic lock table that can be used to lock any kind of record, then take a look at the django.contrib.contenttypes framework, but quickly this can devolve into abstraction astronaut syndrome.
If collisions are unlikely or lost modifications are trivially recreated, then you can functionally get away with optimistic concurrency techniques. This technique is simple and easier to implement. Essentially, you just keep track of a version number or modification time stamp and reject any modifications that you detect as out of whack.
From a functional design standpoint, you only have to consider how these concurrent modification errors are presented to your users.
In terms of Django, optimistic concurrency control can be implemented by overriding the save method on your model class...
def save(self, *args, **kwargs):
if self.version != self.read_current_version():
raise ConcurrentModificationError('Ooops!!!!')
super(MyModel, self).save(*args, **kwargs)
And, of course, for either of these concurrency mechanisms to be robust, you have to consider transactional control. Neither of these models are fully workable if you can't guarantee ACID properties of your transactions.
这篇关于Django模型中的并发控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!