ここにバナナは行きます。並行処理の保護を実装しようとしています。同時実行保護が機能していません
私はそれを行うには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})
(私は同じユーザーを使用)
編集中にコードがサーバー上で実行されていないため、トランザクションの編集中にトランザクションが待機しないようになりました。あなたが非常に運が良ければ、まったく同じ時間に2つのリクエストを実行しない限り、ロックをロックし、アップデートし、リリースする間にエラーは発生しません。ディスク上のバージョン番号チェックでは動作しないのはなぜか正確には言えません。私はそれをやっているように見えるコードは、ブラウザからIDを取得するか、POSTでデータベースから読み取るか? –
楽観的には、別の質問でコメントを受け取りました.https://stackoverflow.com/questions/47692858/data-is-not-being-read-directly-from-the-database-instead-of-buffer-on -2nd-call "データベース自体が別のトランザクションでアイテムをロックしていて、トランザクション分離設定によってこのプロセスが更新された値を参照できなくなっている可能性がありますが、どうすれば対処するかわかりません。 –
しかし、私はコードを正しく読んでいますか?selectを使ってデータベースから 'post'を取得し、保存してから' on_disc'を取得して比較しますか?それらのどちらも以前の*リクエストからのものではなく、* previous *値を持っているからです。これらはどちらも* this *リクエストからのものであり、常に一致します。ブラウザに値を送って戻し、その値を現在の値と比較する必要があります。 –