Django:如何防止并发修改数据库条目
是否有办法防止两个或多个用户同时修改同一个数据库条目?
If there a way to protect against concurrent modifications of the same data base entry by two or more users?
向执行第二次提交/保存操作的用户显示错误消息是可以接受的,但不应以静默方式覆盖数据.
It would be acceptable to show an error message to the user performing the second commit/save operation, but data should not be silently overwritten.
我认为锁定条目不是一种选择,因为用户可能会使用返回"按钮或干脆关闭他的浏览器,从而永远保持锁定状态.
I think locking the entry is not an option, as a user might use the "Back" button or simply close his browser, leaving the lock for ever.
这就是我在 Django 中进行乐观锁的方式:
This is how I do optimistic locking in Django:
updated = Entry.objects.filter(Q(id=e.id) && Q(version=e.version))
.update(updated_field=new_value, version=e.version+1)
if not updated:
raise ConcurrentModificationException()
上面列出的代码可以作为自定义管理器中的方法实现.
The code listed above can be implemented as a method in Custom Manager.
我做出以下假设:
- filter().update() 将导致单个数据库查询,因为过滤器是惰性的
- 数据库查询是原子的
这些假设足以确保之前没有其他人更新过该条目.如果以这种方式更新多行,则应使用事务.
These assumptions are enough to ensure that no one else has updated the entry before. If multiple rows are updated this way you should use transactions.
警告 Django 文档:
注意 update() 方法是直接转换为 SQL陈述.这是一个批量操作直接更新.它不运行任何模型上的 save() 方法,或发出pre_save 或 post_save 信号
Be aware that the update() method is converted directly to an SQL statement. It is a bulk operation for direct updates. It doesn't run any save() methods on your models, or emit the pre_save or post_save signals