2017-01-06 16 views
0

私の問題に少し背景を与えるために、私は非常に基本的な銀行システムを持っています。現時点では、プロセスが行く:複数の更新を1つのdbフィールドに処理する

  1. 取引はAzureのサービスバスに追加され
  2. アンアズールWebjobは、このメッセージをピックアップし、SQL DBに新しい行を作成します。
  3. アカウントの残高(合計)をメッセージの値(+または - )で更新する必要があります。

たとえば、フィールドが10で2つの更新(10、-5)が得られた場合、フィールドは15(10 + 10-5)でなければなりません。値を更新するだけではありませんいくつかの算術演算を行う必要があります。

ここで、多くのリクエストが入る可能性があるので、残高の更新を処理する方法があまりにもわかりません。それに応じて更新する必要があります。

私は、WebジョブではなくSQL側で更新を行うことを考えましたが、これは同時更新では役立ちません。

フィールドでロックすることはできますか?しかし、更新が既に進行中であるためにブロックされた場合、更新はどうなりますか?それは待っているか失敗していますか?待っていればOKです。私はEFを使用しています。

これは別の方法で考えました。これはスケジュールで実行される別のWebJobを持っていて、すべての金額を加算して一度値を更新するので、そのフィールドに触れる唯一のものになります。

おかげ

+0

どのデータベースを使用していますか? –

+0

@ReenactorRob私はAzureでSQL DBを使用しています。私はそれを指定する質問を更新しました。 – ADringer

+1

多くの更新文が高速に実行されないようにするには、30秒間の数値を集計して合計し、dbの現在の残高に加算するジョブを実装することができます。次に、次の30秒間の値を再度集計し、dbの残高値に加算します。この方法では、データベース内のトランザクションが少なくて済み、正しい計算が行われます。 –

答えて

0

一つの方法または別の、あなたは(実際には全体の行に)口座残高フィールドへの書き込みアクセスをシリアル化する必要があります。
「保留中の」挿入を取得し、最終的に更新残高を確認する別のジョブがあると、システムでの書き込みが読み取りよりも頻繁に行われる場合や、最新の残高を常に返す必要はありません。そうでなければ、あなたは間違いなく、パフォーマンスの観点から、より高価ですが、いくつかのシステムのために、それは完全に罰金です

SELECT balance + 
    ISNULL((SELECT SUM(transaction_amount) 
    FROM pending_insert pi WHERE pi.user_id = ac.user_id 
    ),0) as actual_balance 
FROM account ac 
WHERE ac.user_id = :user_id 

ような何かをする必要があります現在の残高を取得します。別の落とし穴(あなたの場合と関連しているかもしれないし、そうでないかもしれない)は、例えば負でないバランスを強要しています。

また、あなたは一貫して、次のように銀行取引を処理することができます

  1. データベーストランザクションを開始
  2. 検索とアカウントテーブルに
  3. 挿入レコードを必要に応じて
  4. 検証総量でロック行banking_transaction
  5. ユーザーアカウントの更新、つまりbalance = balance + transasction_amount
  6. コミット/ロールバック

    複数のユーザーアカウントが関係する場合は、デッドロックを回避するために、常に同じ順序でロックする必要があります。

    アプローチは、より堅牢ですが、ビューの同時実行性の点から潜在的に悪化し(再び、それはあなたのアプリケーションでの更新の性質に依存すること

- ここでは、最悪の場合は、一人のユーザーのために多くの同時銀行取引で、アップデートへ複数のユーザーがうまくいく)。

最後に、SQLServerを使用しているので、ロックエスカレーションによるデッドロックに注意してください。どのような場合でも再試行ロジックを実装する必要があるかもしれません。

0

sqlでパラメータ置換メソッドを使用するとします。 Webジョブで使用しているプログラミング言語に基づいて、その方法を調べる必要があります。

$updateval = -5; 
Update dbtable set myvalue = myvalue + $updateval 

code example: 
int qn = int.Parse(TextBox3.Text) 
SqlCommand cmd1 = new SqlCommand("update product set group1 = group1 + @qn where productname = @productname", con); 
cmd1.Parameters.Add(new SqlParameter("@productname", TextBox1.Text)); 
cmd1.Parameters.Add(new SqlParameter("@qn", qn)); 

が実行されます。

関連する問題