2011-09-24 10 views
4

SQL ServerのようなRDBMSを使用して、Webアプリケーションプログラミングと同時処理を初めて導入しました。私はSQL Server 2005 Express Editionを使用しています。私は同時接続が原因で発生する可能性のある問題を処理する方法を、次のではないのです並行環境で最大(ID)を扱う

SELECT max(ID) FROM employees WHERE district = "XYZ"; 

私は最後の4桁が、このクエリから来ている従業員のコードを生成しています。多くのユーザーが同じ最大(ID)を選択でき、1人のユーザーが[レコードを保存]をクリックしている間に、別のユーザーがIDを既に占有している可能性があります。

この問題を処理するにはどうすればよいですか?

+0

自動インクリメント列を使用するか、一度に1つだけ実行するようにクエリをトランザクションにします。 – Joe

+0

自動インクリメント。 – RKh

+0

指定された地区の最大IDを取得しますか?あなたはそのIDで何をしていますか? ID列はID列ですか?いつクエリを実行しますか?挿入直後に新しく作成したIDを何かに使用したいのですか? –

答えて

2

ここには2つの方法があります。 EmpCodeのユニークな制約違反で終わるかもしれないという事実について私は心配するつもりです:)。

1.使用scope_identity()最後に挿入IDを取得し、EmpCodeを計算するためにそれを使用します。

テーブル定義:

create table Employees 
(
    ID int identity primary key, 
    Created datetime not null default getdate(), 
    DistrictCode char(2) not null, 
    EmpCode char(10) not null default left(newid(), 10) unique 
) 

従業員に一列を追加します。あなたはEmpCodeleft(newid(), 10)からデフォルトのランダムな値のままにされないことを確認するためにトランザクションで実行する必要があります。

declare @ID int 

insert into Employees (DistrictCode) values ('AB') 

set @ID = scope_identity() 

update Employees 
set EmpCode = cast(year(Created) as char(4))+DistrictCode+right([email protected], 4) 
where ID = @ID 

2.EmpCodecomputed columnしてください。

表の定義:

create table Employees 
(
    ID int identity primary key, 
    Created datetime not null default getdate(), 
    DistrictCode char(2) not null, 
    EmpCode as cast(year(Created) as char(4))+DistrictCode+right(10000+ID, 4) unique 
) 

は、従業員に1行を追加します。

insert into Employees (DistrictCode) values ('AB') 
1

Transaction Isolation Levelsによって行うことができます。たとえば、SERIALIZABLEをレベルとして指定すると、他のトランザクションがブロックされ、この問題に遭遇していないことになります。

質問が正しく理解できなかった場合は、私にお知らせください。

2

適切なロック機構と、あなたが挿入することができなくなりますので、MAXを使用することが悪い考えです同じ地区の複数のスレッドの行。 一度に1人のユーザーしか作成できない場合や、地区ごとに多数のユーザーがいる場合でもMAXがスケールアップしていることがテストで分かっている場合は、それを使用しても問題ありません。 簡単に言えば、身分証明書を扱うことはできるだけIDENTITYに依存する必要があります。本当に。

しかし、それが不可能な場合は、別のテーブルのIDを処理することが1つの解決策です。

Create Table DistrictID (
    DistrictCode char(2), 
    LastID Int, 
    Constraint PK_DistrictCode Primary Key Clustered (DistrictCode) 
); 

次に、LastIDカウンタをインクリメントします。並列スレッドで多数のユーザーを作成する場合は、IDを増やすことがトランザクションをユーザー作成トランザクションに分離することが重要です。 IDの生成のみを順番に行うように制限することができます。

のコードは次のようになります。

Create Procedure usp_GetNewId(@DistrictCode char(2), @NewId Int Output) 
As 

Set NoCount On; 
Set Transaction Isolation Level Repeatable Read; 
Begin Tran; 
Select @NewId = LastID From DistrictID With (XLock) Where DistrictCode = @DistrictCode; 
Update DistrictID Set LastID = LastID + 1 Where DistrictCode = @DistrictCode; 
Commit Tran; 

反復可能読み取りXLOCKキーワードを使用すると、同じIDを取得するために2つのスレッドを避けるために必要最小限のです。 表はすべての地区を持っていない場合は、Serializableを反復可能読み取りを変更し、挿入更新をフォークする必要があります。