1

2つの列を持つテーブルがあります

key -> Primary Key, auto incremented
reqNumber -> This is a custom generated value

reqNumber は、年/月/日/数字の形式で構成されます。number は、その日にリクエストが行われた回数です。たとえば、今日 3 つのリクエストが行われ、昨日 2 つのリクエストが行われた場合、テーブルは次のようになります。

key    reqNumber
1      2013/07/16/001
2      2013/07/16/002
3      2013/07/17/001
4      2013/07/17/002
5      2013/07/17/003

私が抱えている問題は、複数のユーザーが同時に保存することがあります。保存を行うプロシージャは、最初に今日作成された数をチェックし、それに 1 を追加します。したがって、上記の場合、今日作成されたのは 3 であるため、次は 4 になります。その後、挿入を行います。

しかし、2 人のユーザーが同時に保存を押すと、両方とも 4 になります。つまり、挿入が発生すると、2013/07/17/004 が 2 回得られます。

SQLまたは.Netでこれを回避する方法はありますか? ロックは唯一の方法ですか?ロックはパフォーマンスを低下させますか?

4

3 に答える 3

3

アプリケーションをスケーリングできるようにする場合は、新しいテーブルを作成する必要があります。

CREATE TABLE DayCounter (
    LastReset DateTime NOT NULL,
    NextValue INT NOT NULL
)

次に、FUNCTION次の利用可能な値を自由に取得できるようにする必要があります。

CREATE FUNCTION NextCounter()
    RETURNS CHAR(3)
AS
BEGIN
    BEGIN TRANSACTION
        DECLARE @LastReset DATETIME
        DECLARE @NextValue INT

        SELECT @LastReset = LastReset FROM DayCounter
        IF (DATEPART(DAY, DATEADD(DAY, 1, @LastReset)) = DATEPART(DAY, GETDATE())
            UPDATE DayCounter SET LastReset = GETDATE(), NextValue = 1

        SELECT @NextValue = NextValue FROM DayCounter
        UPDATE DayCounter SET NextValue = NextValue + 1
    COMMIT TRANSACTION

    RETURN RIGHT('000' + CAST(@NextValue AS CHAR), 3)
END

これで、値をつなぎ合わせる update ステートメントを作成できますが、衝突から保護され毎日のリセットを管理します。

于 2013-07-17T14:48:31.063 に答える
1

reqNumber が一意でなければならない場合、データベースUNIQUEには列に対する制約が必要です。これを追加すると、別のオプションが提供されます。ロックなしで 1 回試行し、挿入が失敗した場合は、ロックを使用して再試行します。読み取り/書き込み比率が高く、衝突頻度が低いため、トランザクションごとのソリューションよりもはるかに優れたパフォーマンスを発揮できます。

于 2013-07-17T16:11:36.933 に答える