問題タブ [optimistic-locking]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
4 に答える
671 参照

ruby-on-rails - 2 人が同時に編集を送信するとどうなりますか

これはばかげた質問かもしれませんが、2 人のユーザーが一度にデータを編集し、両方が同時に送信をクリックするとどうなるかを知りたかったのです。これは正しいですか?

ありがとう

1 人のユーザーがデータを編集したら、それ以上アクセスしたり編集したりしたくありません。これは検証によって処理されます。

私のモデルでもこの​​検証を受けました

検証に合格した場合、アクティブな場所はコントローラー内のブール値セットです

0 投票する
2 に答える
8231 参照

ruby-on-rails - Railsアプリで競合状態を回避するにはどうすればよいですか?

私は、ユーザーが一連のコースへの出席を登録できる、非常にシンプルなRailsアプリケーションを持っています。ActiveRecordモデルは次のとおりです。

ScheduledRunインスタンスには、使用可能な場所の数に制限があり、制限に達すると、それ以上の出席を受け入れることができなくなります。

Atcentances_countは、特定のScheduledRunレコードに対して作成された出席アソシエーションの数を保持するカウンターキャッシュ列です。

私の問題は、1人以上の人が同時にコースの最後の利用可能な場所に登録しようとしたときに、競合状態が発生しないようにする正しい方法を完全に知らないことです。

私の出席コントローラーは次のようになります。

ご覧のとおり、ScheduledRunインスタンスがすでに容量に達した場所は考慮されていません。

これに関する助けをいただければ幸いです。

アップデート

この場合、これが楽観的ロックを実行する正しい方法であるかどうかはわかりませんが、これが私が行ったことです。

ScheduledRunsテーブルに2つの列を追加しました-

また、ScheduledRunモデルにメソッドを追加しました。

出席モデルが保存されると、ActiveRecordは先に進み、ScheduledRunモデルのカウンターキャッシュ列を更新します。これがどこで発生するかを示すログ出力です-

新しい出席モデルが保存される前にScheduledRunモデルに後続の更新が発生した場合、これによりStaleObjectError例外がトリガーされます。その時点で、容量にまだ達していない場合は、すべてが再試行されます。

アップデート#2

@kennの応答に続いて、SheduledRunオブジェクトの更新されたattendメソッドがあります。

0 投票する
0 に答える
1567 参照

mysql - ActiveRecord :: Base.connection.update(sql)は、影響を受ける行の数が正しくない場合があります

次の環境の本番Webサイトがあります。

  • レール2.3.5
  • MySQLサーバー5.1.33
  • Enterprise Ruby 1.8.6(2008-08-11パッチレベル287)[x86_64-linux]
  • mysql gem 2.7
  • バックグラウンドタスク用に4つの異なるサーバーで実行されている古いバージョンのBackgrounDRbプラグインで、それぞれ5つの異なるワーカーがあります(Rubyスレッド、個別のプロセスではありません!)。

BackgrounDRbワーカーの1つは、「楽観的ロック」のバリエーションを使用してジョブキューを処理します。

上記のコードは、指定されたIDとin_processフィールドの追加条件でレコードを更新しようとします。したがって、この同じレコードが別のサーバー/プロセスによってすでに更新されている場合、UPDATEステートメントは0(ゼロ)を返すだけで、ジョブは2つの異なるサーバーによって同時に処理されません。

問題は次のとおりです。レコードが実際に更新された場合でも、「Job.connection.update(update_sql)」が0(ゼロ)を返すことがあります。大量のロギングがコードに追加された後でのみ、それを見つけることができました。それは私たちが重い負荷をかけている夜のプロダクションでのみ起こります...

私の推測では、mysql gemは、BackgrounDRbプロセスの5つのスレッドすべてで共有されるaffected_rowsにグローバル変数(クラス変数)を使用していると思いますが、よくわかりません。mysql gemとActiveRecordのコードを調べていましたが、実際にどのように機能するのか理解できませんでした。

これはどのように起こりますか?

更新2010-07-07:ジョブ処理にスレッドを使用しないことにしました-これですべての問題が解決します:すべてのジョブプロセッサは個別のプロセスになります:)

0 投票する
4 に答える
16818 参照

java - Spring Optimistic Locking:コミットが成功するまでトランザクションメソッドを再試行する方法

私はSpring2.5とHibernateJPAの実装をJavaと「コンテナー」管理トランザクションで使用しています。

バックグラウンドでデータを更新する「ユーザーコミット後」メソッドがあり、クライアントに表示されることはないため、例外にConcurrencyFailureException関係なくコミットする必要があります。StaleObjectStateException言い換えれば、楽観的なロックを悲観的にする必要があります。(メソッドの実行に少し時間がかかり、誰かが他のトランザクションでデータを変更した場合に発生する可能性があります)


べき等について多くのことを読みました。DEFAULT_MAX_RETRIESまたは6.2.7の検索で例外が発生した場合は、再試行してください。例または第14.5章。再試行します。私はここここのstackoverflowでも見つけました。

私はこれを試しました:

RetryOnConcurrencyException例外が発生した場合に再試行する必要があるメソッドをマークするためのアノテーションです。動作しませんでした...私もいくつかの方法を試しましたSELECT ... FOR UPDATEEntityManager.lock(...)

Springでこのような戦略を使用して、古いデータやダーティリードなどを回避するための最良の方法は何ですか?再試行?、同期?、JPAロック?、分離?、更新のために...を選択しますか?私はそれを機能させることができませんでした、そして私はどんな助けにも本当に満足しています。


これが私がやりたい擬似コードです:

//XXXと//YYYの間で、別のセッションがアイテムを変更する可能性があり、StaleObjectStateExceptionがスローされます。

0 投票する
2 に答える
2128 参照

hibernate - ReSTful アプリでのサーバー側楽観的ロック: 同じクライアントからの非同期リクエストの処理

私は、概念実証からパイロット プロジェクトに値する何かに移行中のプロジェクトに取り組んでいます。この開発フェーズの重要な改善点の 1 つは、メモリに保持され、定期的にファイルにダンプされるハッシュ テーブルを使用する現在の「持続性」メカニズムから、より従来型のデータベース バックエンドに移行することです。

アプリケーション自体は、ReSTful の原則を念頭に置いて設計されています。Jersey を使用してリソースへのアクセスを提供し、jQuery を使用してこれらのリソースをユーザーに提示し、基本的な対話 (作成、更新、削除) を有効にします。かなり簡単です。

リレーショナル データベースでサーバー側の状態を永続化するために、過去に JPA と Hibernate を使用して成功したことがあるので、この場合は当然の選択に思えました。モデル エンティティにいくつかのマイナーな変更を加えることで、基本的な読み取り、作成、および削除操作を適切な時間内に実行できるようになりました。ただし、更新操作はより困難であることが判明しました。

アプリケーションのクライアント側部分は、ユーザーがリソースを変更してから数秒後に変更をサーバーに自動的に送信します。さらに、ユーザーがホームページに戻る直前にリソースの最新バージョンをサーバーに送信するために押すことができる「保存して閉じる」ボタンがあります。

私の最初の問題は、管理対象エンティティをデータベースから、クライアントからの管理対象外オブジェクトで更新する方法でした。クライアントに送信されるデータは意図的にデータベース キーを省略しているため、管理されていないオブジェクトの要素を Hibernate オブジェクトに明示的に「マージ」することになるため、これは少し面倒でした。これは私の質問ではありませんが、これを行うエレガントな方法を知っている人がいれば、ぜひ聞いてみたいと思います。

私の 2 番目の問題、およびこの記事の目的は、前述の自動保存操作が行われているのとほぼ同時に「保存して閉じる」ボタンを押したときに発生します。多くの場合、楽観的ロック例外が発生します。これは、最初の更新操作がまだ処理されている間に、2 番目の更新操作が別のスレッドで処理されているためです。

リソースには、更新が処理されるたびに設定される「更新された」タイムスタンプがあるため、データベースへの更新は、何も変更されていなくても毎回保証されます。これ自体はおそらく問題ですが、修正した後でも、自動保存の進行中にユーザーが変更を加えてサーバーに送信できる「機会の窓」がまだあり、同じ問題を引き起こします.

この問題に対処するために私が考えることができる最も簡単なアプローチは、クライアント側の Javascript の一部を作り直して、そのクライアントからの未解決の「更新」操作が常に 1 つだけになるようにすることです。(別のクライアントがたまたま同じリソースを同時に更新した場合、楽観的ロック例外はまったく問題ないことに注意してください。) ただし、クライアントにこの制限を強制することは、ReST の精神から逸脱する可能性があることを懸念しています。ReSTfulアプリケーションの任意の時点で、特定のクライアントが特定のリソースに対する未処理の「更新」(PUT)リクエストを1つしか持たないと期待するのは合理的ですか?

これはかなり一般的なシナリオのように思えますが、それを処理する最善の方法について決定的な答えを見つけることができませんでした. 私が検討して破棄したその他のアイデアには、同じクライアントからのリクエストを (おそらく HTTP セッションに基づいて) 何らかの方法でシリアル化し、順番に処理されるようにすること、JPA/Hibernate ワーカー スレッドの更新の「キュー」を実装すること、および新しい "単一のレコードを更新するのではなく、最新のものを追跡しながら、リソースのバージョン"。

何かご意見は?クライアントでの「一度に 1 つの未処理の更新」という制限は合理的に見えますか、それともより良いアプローチがありますか?

0 投票する
2 に答える
869 参照

java - OptimisticLockException を発生させる方法

楽観的ロック例外をキャッチできません。

OptimisticLockException を発生させる 1 つの方法は、em.flush() を使用することです。

しかし、この完全なデータベースはフラッシュされているため、これが最善の解決策だとは思いません。

別の回避策は、その中でキャッチEJBExceptionして見つけるRollBackExceptionことです..

他に考えがあるか、どちらの方法が良いか教えてください。

0 投票する
2 に答える
3611 参照

hibernate - Null @Version 列の org.springframework.transaction.UnexpectedRollbackException

Spring 3.0.4-RELEASE、JPA 2.0 を Hibernate をプロバイダーとして使用し、JTA JOTM をアプリケーションのトランザクションに使用しています。entityManager.mergeエンティティ オブジェクトを呼び出すと、次のエラーが発生しました。

このエラーは、Talend ETL ジョブを介してデータベース (MySQL) にデータを直接挿入した結果として発生しました。@Versionデータベース内の列に値があることに気付き、NULL値を 0 に設定することにしました。これで問題が解決しました。

@Version列ができないのはなぜNULLですか? 他の誰かがこの問題に遭遇しましたか? ありがとう。

0 投票する
6 に答える
1559 参照

testing - Grails アプリケーションの同時変更テストを行う方法

grails アプリケーションの特定のデータを同時に変更するユーザーをシミュレートするテストを実行したいと考えています。

これを効率的に行うために使用できるプラグイン/ツール/メカニズムはありますか? それらは Grails 固有である必要はありません。複数のアクションを並行して起動できる必要があります。

ユーザーの観点から結果を確認するには、機能レベルでテストを実行することをお勧めします (これまでのところ、他のテストには Selenium を使用しています)。もちろん、統合レベルでも同時変更テストを実行することをお勧めする場合は、統合テストに加えてこれを行うことができます。

0 投票する
1 に答える
3680 参照

hibernate - grails サービスで StaleObjectStateException を克服する方法

楽観的なトランザクションを実行するためにコントローラーで使用する TransactionService を導入しました。そうすべき

  • 与えられたトランザクションを実行しようとする (= 閉鎖)
  • 失敗した場合はロールバックし、
  • 失敗したらもう一度試す

基本的には次のようになります。

もう少し複雑です。たとえば、再試行する前に別の Thread.sleeps を使用し、ある段階で中止しますが、ここでは問題ではありません。クロージャーとして安全に実行されるトランザクションを渡すコントローラーから呼び出されます。

私の問題:サービスが同時更新のために org.hibernate.StaleObjectStateException にヒットすると、再試行を続けますが、例外は消えません。

コントローラーから渡されたトランザクションでドメインクラスを再アタッチしたり、サービスまたはコントローラーでセッションをクリアしたりするなど、すでにさまざまなことを試しましたが、役に立ちませんでした。私は何が欠けていますか?

status.createSavepoint() を使用して transaction() が呼び出される前に savePoint を挿入しようとすると、「Transaction Manager はネストされたトランザクションを許可しません」というエラーが発生したことに注意してください。トランザクションがコントローラーからサービスに渡されるためにエラーが存在し、それを回避するために新しい/ネストされたトランザクションを開始する必要があるのではないかと疑ったため、これを試しましたが、エラーが示すように、私の場合は不可能です。

それとも、トランザクションをクロージャーとして渡すことが問題なのでしょうか?

.withTransaction の前に使用されるドメイン クラスは問題ではないと思いますか?

0 投票する
1 に答える
1751 参照

oracle - NHibernateOracle データベースのマッピングで StaleStateException が発生する

SQL Server から Oracle に移行する NHibernate アプリがあります。オプティミスティック コンカレンシーは、<timestamp name="Version">マッピング要素を介して実装されます。

VersionOracle の対応する列のデータ型は ですDATE。オブジェクトを保存した後、メモリ内の C# オブジェクトにはミリ秒単位のタイムスタンプ値 (例: 12:34:56.789) が残りますが、データベースの値は秒単位 (例: 12:34:56) までしか正確ではありません。したがって、オブジェクトを 2 回保存しようとすると、2 つの値が一致しないため、StaleStateException が発生します。

Version列のデータ型を に変更して、これを修正しようとしましたTIMESTAMP(3)。残念ながら、C# オブジェクトと DB 値はまだ 1 ミリ秒ずれているため (例: 12:34:56.789 対 12:34:56.788)、オブジェクトを 2 回保存しようとすると、StaleStateException が発生します。

<timestamp>タイプの Or​​acle 列への有効なマッピングを作成しDATEたりTIMESTAMP、同じオブジェクトを複数回保存できるようにするにはどうすればよいですか?

ありがとう。

-- ブライアン