私は、顧客から金額取引をアップロードしてSQL Server DBに保存するためのエンドポイントとして機能する非常に簡単なWebアプリケーションを作成しています。 2つのパラメータ(userid: 'xxx', balancechange: -19.99
)でリクエストを受け入れます。ユーザーIDがappデータベースに存在する場合、残高は変更されます。そうでない場合は、このIDに対して新しい行が作成されます。ASP.NET WebAPI + SQLの同時実行制御を正しく実装する
難しい点はリクエスト数が膨大で、できるだけ速く動作するようにアプリケーションを実装しなければならないことです(同じIDに対する2つのリクエストが同時に到着した場合)。
このアプリはASP.NET MVC WebAPIです。私はスピードのために、昔ながらのADO.NETを使用することを選択したが、これは私が現在持っているものである。このようなコントローラから呼び出され
private static readonly object syncLock = new object();
public void UpdateBalance(string userId, decimal balance)
{
lock (syncLock)
{
using (var sqlConnection = new SqlConnection(this.connectionString))
{
var command = new SqlCommand($"SELECT COUNT(*) FROM Users WHERE Id = '{userId}'", sqlConnection);
if ((int)command.ExecuteScalar() == 0)
{
command = new SqlCommand($"INSERT INTO Users (Id, Balance) VALUES ('{userId}', 0)", sqlConnection);
command.ExecuteNonQuery();
}
command = new SqlCommand($"UPDATE Users SET Balance = Balance + {balance} WHERE Id = {userId}", sqlConnection);
command.ExecuteNonQuery();
}
}
}
:
は[HttpPost]
public IHttpActionResult UpdateBalance(string id, decimal balanceChange)
{
UpdateBalance(id, balanceChange);
return Ok();
}
私はconcernredてる事は同時実行でありますlock (syncLock)
を使用して制御します。これは、負荷が高い状態でアプリを遅くし、アプリの複数のインスタンスを異なるサーバーにデプロイすることを許可しません。ここでは、並行処理制御を適切に実装する方法は何ですか?
注:現在のストレージメカニズム(SQL Server)が将来変更される可能性があるため、高速でDBに依存しない並行性制御の実装方法を使用したいと思います。
追加はアソシエイティブなので、バランスの変更が順番に行われるのはなぜですか?さらに高速化が必要な場合は、インライン(注入の傾向がある)文字列ではなく、ストアドプロシージャでカプセル化する必要があります。 – Crowcoder
'userId'変数が文字列であるため、SQLコードはSQLインジェクションのためにオープンされています。パラメータ化されたクエリを使用します。 – jgauffin
あなたのロックは行ごとに分散していなければならず、DBトランザクションが必要です。なぜ私はあなたがそのような脆弱なアプローチを使用して再実装しようとしているのか分かりません。 –