2017-12-08 17 views
0

ここにバナナは行きます。並行処理の保護を実装しようとしています。同時実行保護が機能していません

私はそれを行うには2つの方法があります。 オプティミスティック - 基本的にレコードにバージョンフィールドを追加し、それぞれのセーブでレコードが増えます。私の現在のバージョンフィールドがディスク上のものと異なる場合、何かが変更されたことを意味し、私はエラーを出します。

悲観的なアプローチは、単にレコードをロックすることを意味し、編集することはできません。

私は両方の方法とDjangoの同時実行パッケージを実装しましたが、何も私はSQLLiteとHerokuのPostgresで丁寧に動作します。

以下

それは両方持っている悲観的のために

に近づく私の見解方法で、私はselect_for_update を用いた原子トランザクションとロックと楽観的のために、私は、各編集上の私のバージョンフィールドが増加同時実行Djangoのパッケージを使用して、との単純な比較を行いますon_discの値

私は間違っていますか?助けてください?同じレコードで私はちょうどオープン2つのブラウザテストと並行して両方を編集しようとする

@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}) 

(私は同じユーザーを使用)

+0

編集中にコードがサーバー上で実行されていないため、トランザクションの編集中にトランザクションが待機しないようになりました。あなたが非常に運が良ければ、まったく同じ時間に2つのリクエストを実行しない限り、ロックをロックし、アップデートし、リリースする間にエラーは発生しません。ディスク上のバージョン番号チェックでは動作しないのはなぜか正確には言えません。私はそれをやっているように見えるコードは、ブラウザからIDを取得するか、POSTでデータベースから読み取るか? –

+0

楽観的には、別の質問でコメントを受け取りました.https://stackoverflow.com/questions/47692858/data-is-not-being-read-directly-from-the-database-instead-of-buffer-on -2nd-call "データベース自体が別のトランザクションでアイテムをロックしていて、トランザクション分離設定によってこのプロセスが更新された値を参照できなくなっている可能性がありますが、どうすれば対処するかわかりません。 –

+0

しかし、私はコードを正しく読んでいますか?selectを使ってデータベースから 'post'を取得し、保存してから' on_disc'を取得して比較しますか?それらのどちらも以前の*リクエストからのものではなく、* previous *値を持っているからです。これらはどちらも* this *リクエストからのものであり、常に一致します。ブラウザに値を送って戻し、その値を現在の値と比較する必要があります。 –

答えて

0

問題は、ウェブサイトがどのように働くかを使用することです。現在、あなたのロックは次のように動作します。

  • GETリクエストデータをロードし
    • あなたが行をロック、負荷、ブラウザに送る、あなたがブラウザ
    • POSTでデータを編集
  • のロックを解除サーバーへのデータ
    • ローをロックし、更新し、ロックを解除します。

行をロックしたままにするものは何もありません。各要求後に行がロック解除されるので、複数インスタンスはサーバーにデータを送信できます。これはWebシステムが通常動作する方法です。それぞれの要求は別々であり、ロックは別々に実行する必要があります。

行のバージョン管理については、コードを正しく理解すれば、現在の行番号はブラウザに送信されませんが、更新中はそれを読んでいます。これは、正しい番号を取得することを再度意味します。現在の番号をブラウザに送信し、POSTでその番号をデータベースの現在の番号と比較する必要があります。このようにして何かが変化した場合、それが検出されます。

私はDjangoに慣れていないので、この部分について間違っているかもしれませんが、これはコードの機能を私が理解していることです。私はformが現在の行のバージョンを持っているかもしれないと仮定しますが、それは何も比較されていません。データベースの現在の番号と更新後の番号だけです。

+0

私はしませんでしたそれはまだ動作させる。フォームからバージョンを取得する際に問題が発生しています。しかし、私はあなたが正しいと思います。ありがとうございました –

関連する問題