并发保护不起作用

时间:2017-12-08 10:34:06

标签: django postgresql heroku concurrency

我去香蕉吧。我试图实现并发保护。

所以我发现有两种方法可以做到这一点。 乐观 - 基本上我们在记录中添加一个版本字段,每次保存都会增加它。因此,如果我当前的版本字段与光盘上的版本字段不同,则意味着某些内容已被修改,我会给出错误。

悲观的方法意味着我们只是锁定一条记录而且无法编辑。

我为Django实现了两种方式加上并发包,没有任何方法可以在SQLLite和Postgres上使用Heroku。

以下是我的查看方法,它有两种方法

对于悲观,我使用select_for_update锁定事务原子 为了乐观,我使用并发django包,在每次编辑时增加我的版本字段并与on_disc值进行简单比较

我做错了什么?请帮帮忙?

@login_required
    def lease_edit(request,pk,uri):
        logger = logging.getLogger(__name__)
        title = 'Edit Lease'
        uri = _get_redirect_url(request, uri)


        with transaction.atomic():

            post = get_object_or_404(Lease.objects.select_for_update(), pk=pk)

            if request.method == "POST":
                form = LeaseForm(request.POST, instance=post)
                if form.is_valid():
                    lease = form.save(commit=False)
                    on_disc= Lease.objects.get(pk=post.id)
                    if on_disc.version > post.version:
                        messages.add_message(request, messages.ERROR, str(lease.id) + "-Error object was modified by another user. Please reopen object.")
                        return redirect(uri)


                    lease.save()
                    messages.add_message(request, messages.SUCCESS, str(lease.id) + "--SUCCESS Object saved successfully")
                    return redirect(uri)
            else:
                form = LeaseForm(instance=post)
            #lease = post.lease 
            return render(request, 'object_edit.html', {'form': form, 'title':title, 'extend': EXTEND})

要测试我只打开2个具有相同记录的浏览器并尝试并行编辑(我使用相同的用户)

1 个答案:

答案 0 :(得分:0)

问题在于网站的运作方式。目前您的锁定工作方式如下:

  • GET请求加载数据
    • 您锁定行,加载,发送到浏览器,解锁
  • 您在浏览器上编辑数据
  • 将数据发布到服务器
    • 您锁定行,更新,解锁

此处没有任何内容可以阻止行。多个实例可以将数据发送到服务器,因为在每个请求之后行被解锁。这是Web系统通常工作的方式,每个请求都是独立的,锁定必须以不同方式完成。

对于行版本控制,如果我正确理解了代码,您不会将当前行号发送到浏览器,但是在更新时会读取它。这再次意味着您获得了正确的数字。您应该将当前号码发送到浏览器,并在POST时将该号码与数据库中的当前号码进行比较。这样,如果有什么变化,就会检测到它。

由于我不熟悉Django,我可能错了这部分,但这是我对代码功能的理解。我认为form可能有当前行版本,但它没有与任何东西进行比较,只有数据库中的当前数字和更新后的数字(可能也可能更改数字)。