我怎样才能防止数据库条目的并发修改
2016-05-07
展开全部
1. 事实上,交易不帮你在这里多...除非你想有运行在多个HTTP请求(你很可能不希望)的交易。 有什么用在这些情况下是“乐观锁定”。 Django的ORM不支持,据我所知。但一直以来关于添加此功能。 那么,你是你自己的。基本上,你应该做的就是添加一个“版本”字段,你的模型,并把它传递给一个隐藏字段。正常周期的更新是: 读取数据并显示给 用户可以修改数据 用户发布的数据 该应用程序将其保存回数据库。 乐观锁,当你保存数据,你检查,如果你得到了从后面的版本是作为一个在数据库中,然后更新数据库和版本。如果它们不是,那有一直以来被加载的数据的变化。 你可以做到这一点与像一个单一的SQL调用:UPDATE ... WHERE version = 'version_from_user';
这个调用将更新数据库只有在版本仍然是
2. 我就是这样做的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()
上面列出的代码可以在自定义管理。 我提出以下假设: 筛选()。update()方法会导致在一个单一的数据库查询过滤器是懒惰 数据库查询是原子 这些假设都足以确保没有其他人之前已经更新了条目。如果有多个行被更新这样你的交易。 警告Django的文件: 请注意,update()方法是 直接转换为SQL 这是一个批量操作 直接更新。它不运行任何 保存(您的模型)的方法,或发出 该pre_save或post_save信号
3. 这个问题是有点老了,我的回答有点晚,但经过我的理解使用这个已被固定在Django 1.4:select_for_update(nowait=True)
看到文档 返回一个QuerySet,将锁定行,直到事务结束,产生一个SELECT ...有关支持的数据库UPDATE的SQL。 通常情况下,如果另一个事务已获得所选择的行上的锁,则查询将阻塞,直到锁被释放。如果这不是你想要的行为,请致电select_for_update(NOWAIT=TRUE)。这将使调用非阻塞的。如果已经获取了冲突的锁被另一个事务时的QuerySet进行评估,DatabaseError的将得到提升。 当然,这只会工作,如果后端支持的“选择更新”功能,这对于例如SQLite不。不幸的是:nowait=True不支持MySql的,有你有nowait=False,这只会阻塞,直到锁被释放。
4. 对于未来的参考,退房离开的时候(在浏览器中,例如崩溃)的页面,并锁定它锁定的方式,不留下永恒的锁,通过javascript的解锁的混合物。下
5. 你应该Django的交易中间件,至少,甚至不管这个问题。 至于你实际有编辑数据的问题...是的,使用锁。或: 检查什么版本正在更新对(这样做牢固,不能简单地破解系统说,他们正在更新的最新副本!),且仅当该版本是最新的更新。否则,返回一个新页面与原来的版本,他们编辑,他们提交的版本,和别人写的新版本(S)。问他们变成一体,完全取决于最新的版本。你可以尝试类似的diff +补丁工具集,但你需要有方法工作失败的案例,无论如何,所以开始了。此外,您将需要保存的版本历史记录,并允许管理员恢复的变化,在无意的情况下或向上,但你应该有反正。 有很可能是Django应用程序/库,做这个最适合你。
6. 为了安全起见,数据库需要支持事务。 如果字段是“自由形式”如文字等等,你需要允许可以编辑的字段(你不能有所有权的数据),你可以存储在变量中的原始数据。 当committs,检查输入数据从原始数据更改(如果不是,你不需要通过重写旧数据打扰DB) 如果原来在数据库中的当前数据是可以保存,如果它改变了你可以示区别,并问该怎么办。 如果字段是一个数字如账户余额,在商店等项目的数量,你可以自动处理它,如果你计算出原始值(存储开始时填写表单)和新的价值,你就可以开始一个事务读取当前值之间的差额新增的差别,然后结束交易。如果你不能有负值,则应该中止交易,如果结果为负,并告诉 我不知道Django的,所以我不能给你德cod3s .. ;)
7. 另一个需要注意的是这个词“原子”.a个原子,你的数据库的更改要么发生或无法快速搜索说明这个问题问Django中的原子操作。
8. 上面的想法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()
看起来不错,应该能正常运行,即使没有序列化的交易。 问题是如何将deafult。保存()的行为,以不必须做人工管道来调用。update()方法。 我看着自定义管理想法。 我的计划是覆盖被称为Model.save_base()来执行更新的经理。 这是在Django 1.3当前代码def _update(self, values, **kwargs):
return self.get_query_set()._update(values, **kwargs)
什么需要恕我直言做的是这样的:def _update(self, values, **kwargs):
#TODO Get version field value
v = self.get_version_field_value(values[0])
return self.get_query_set().filter(Q(version=v))._update(values, **kwargs)
类似的事情需要发生的删除。但是删除是有点难度的Django是相当巫术在这方面通过django.db.models.deletion.Collector。 这是奇怪的,像Django的modren工具缺乏对Optimictic Concurency控制指导。 当我解开这个谜,我会更新这个帖子。希望解决方案将是不涉及万吨编码,怪异的意见,跳绳重要部分的Django等的一个很好的Python的方式
9. 从这里开始: 我假设将举行一个隐藏字段中你试图挽救细节的表格。def save(self):
if(self.id):
foo = Foo.objects.get(pk=self.id)
if(foo.timestamp > self.timestamp):
raise Exception, "trying to save outdated Foo"
super(Foo, self).save()
这个调用将更新数据库只有在版本仍然是
2. 我就是这样做的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()
上面列出的代码可以在自定义管理。 我提出以下假设: 筛选()。update()方法会导致在一个单一的数据库查询过滤器是懒惰 数据库查询是原子 这些假设都足以确保没有其他人之前已经更新了条目。如果有多个行被更新这样你的交易。 警告Django的文件: 请注意,update()方法是 直接转换为SQL 这是一个批量操作 直接更新。它不运行任何 保存(您的模型)的方法,或发出 该pre_save或post_save信号
3. 这个问题是有点老了,我的回答有点晚,但经过我的理解使用这个已被固定在Django 1.4:select_for_update(nowait=True)
看到文档 返回一个QuerySet,将锁定行,直到事务结束,产生一个SELECT ...有关支持的数据库UPDATE的SQL。 通常情况下,如果另一个事务已获得所选择的行上的锁,则查询将阻塞,直到锁被释放。如果这不是你想要的行为,请致电select_for_update(NOWAIT=TRUE)。这将使调用非阻塞的。如果已经获取了冲突的锁被另一个事务时的QuerySet进行评估,DatabaseError的将得到提升。 当然,这只会工作,如果后端支持的“选择更新”功能,这对于例如SQLite不。不幸的是:nowait=True不支持MySql的,有你有nowait=False,这只会阻塞,直到锁被释放。
4. 对于未来的参考,退房离开的时候(在浏览器中,例如崩溃)的页面,并锁定它锁定的方式,不留下永恒的锁,通过javascript的解锁的混合物。下
5. 你应该Django的交易中间件,至少,甚至不管这个问题。 至于你实际有编辑数据的问题...是的,使用锁。或: 检查什么版本正在更新对(这样做牢固,不能简单地破解系统说,他们正在更新的最新副本!),且仅当该版本是最新的更新。否则,返回一个新页面与原来的版本,他们编辑,他们提交的版本,和别人写的新版本(S)。问他们变成一体,完全取决于最新的版本。你可以尝试类似的diff +补丁工具集,但你需要有方法工作失败的案例,无论如何,所以开始了。此外,您将需要保存的版本历史记录,并允许管理员恢复的变化,在无意的情况下或向上,但你应该有反正。 有很可能是Django应用程序/库,做这个最适合你。
6. 为了安全起见,数据库需要支持事务。 如果字段是“自由形式”如文字等等,你需要允许可以编辑的字段(你不能有所有权的数据),你可以存储在变量中的原始数据。 当committs,检查输入数据从原始数据更改(如果不是,你不需要通过重写旧数据打扰DB) 如果原来在数据库中的当前数据是可以保存,如果它改变了你可以示区别,并问该怎么办。 如果字段是一个数字如账户余额,在商店等项目的数量,你可以自动处理它,如果你计算出原始值(存储开始时填写表单)和新的价值,你就可以开始一个事务读取当前值之间的差额新增的差别,然后结束交易。如果你不能有负值,则应该中止交易,如果结果为负,并告诉 我不知道Django的,所以我不能给你德cod3s .. ;)
7. 另一个需要注意的是这个词“原子”.a个原子,你的数据库的更改要么发生或无法快速搜索说明这个问题问Django中的原子操作。
8. 上面的想法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()
看起来不错,应该能正常运行,即使没有序列化的交易。 问题是如何将deafult。保存()的行为,以不必须做人工管道来调用。update()方法。 我看着自定义管理想法。 我的计划是覆盖被称为Model.save_base()来执行更新的经理。 这是在Django 1.3当前代码def _update(self, values, **kwargs):
return self.get_query_set()._update(values, **kwargs)
什么需要恕我直言做的是这样的:def _update(self, values, **kwargs):
#TODO Get version field value
v = self.get_version_field_value(values[0])
return self.get_query_set().filter(Q(version=v))._update(values, **kwargs)
类似的事情需要发生的删除。但是删除是有点难度的Django是相当巫术在这方面通过django.db.models.deletion.Collector。 这是奇怪的,像Django的modren工具缺乏对Optimictic Concurency控制指导。 当我解开这个谜,我会更新这个帖子。希望解决方案将是不涉及万吨编码,怪异的意见,跳绳重要部分的Django等的一个很好的Python的方式
9. 从这里开始: 我假设将举行一个隐藏字段中你试图挽救细节的表格。def save(self):
if(self.id):
foo = Foo.objects.get(pk=self.id)
if(foo.timestamp > self.timestamp):
raise Exception, "trying to save outdated Foo"
super(Foo, self).save()
2016-05-07 · 百度知道合伙人官方认证企业
育知同创教育
1【专注:Python+人工智能|Java大数据|HTML5培训】 2【免费提供名师直播课堂、公开课及视频教程】 3【地址:北京市昌平区三旗百汇物美大卖场2层,微信公众号:yuzhitc】
向TA提问
关注
展开全部
Oracle数据库的话,使用select for update对结果集进行加锁。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询