2017-08-14 3 views
1

私はJava、Spring、Hibernate、およびOracle SQLでカウンタを実装しようとしています。各レコードは、所与のタイムスタンプによってカウントを表す。各レコードが分単位で一意に識別され、各レコードがカウント列を保持しているとします。このサービスは、1トンの同時リクエストを受け取ると予想され、私はおそらく同じレコードのカウンターコラムを更新します。レコードが存在しない場合は、私のテーブルでsaveOrUpdateで重複レコードを作成するHibernateの同時実行性

、わずかにレコードを挿入し、それ以外の場合は1にそのカウントを設定し、タイムスタンプによるレコードを検索し、するために、1

により、既存のカウンターの列を増やします私たちがデータの一貫性と整合性を維持していることを確認するために、私は悲観的なロックを使用しています。たとえば、同じユーザーではなく、同時に20カウントが入る場合は、更新前にそのレコードの古くなった読み取りからレコードを上書きする可能性があります。ロックを使用すると、20カウントが入ると、データベースへの影響は20カウントになるはずです。

ロックは問題ありませんが、問題は、レコードが最初に存在しなかった場合、同時に存在しないレコードを更新しようとする2つ以上の同時リクエストがある場合です。存在しないレコードをロックすることができないため、重複レコードが挿入されることに注意してください。どのように重複がテーブルに作成されないようにすることができますか?それはOracle経由で制御する必要がありますか?それとも、私のアプリとHibernateでこれを管理できますか?

ありがとうございます。

答えて

0

このような問題を回避するには、データを実際に照会するときにカウントを生成するだけでした。 Oracleには、問合せの結果セット内の各レコードに行番号を割り当てることができる解析機能ROW_NUMBER()があります。ラフ例として、次のクエリを考えてみます。

SELECT 
    ts, 
    ROW_NUMBER() OVER (ORDER BY ts) rn 
FROM yourTable 

したいカウントがテーブルの最初のエントリ以来、登場するレコードの数を表すrn列になります。もちろん、クエリをさらに制限することができます。

この手法は、レコードが削除されると堅牢です。カウントは常に1から始まるため、行番号機能はHibernateではサポートされていません。これをネイティブクエリまたはストアドプロシージャとして実行する必要があります。

関連する問題