2

同じアプリケーションの 2 つの異なるインスタンスから同じストアド プロシージャを同時に実行するとタイムアウトするように見える問題があり、それを解決するために何かできることはないかと考えました。

問題は、SQL Server 2008 がそれ自体を処理し、行をロックし、SP を実行する方法にあると思います。アプリはADODB.CommandSP の実行に使用します。

App.exe1つのサーバー上で複数回実行されている 1 つの VB6 exe ( ) があります。このアプリは、そのアプリの次のシーケンス番号を返すデータベースのストアド プロシージャを呼び出します。tbl_SequenceNosこのシーケンス番号フィールドは、アプリケーションのインスタンスに対して一意です。実行中のアプリケーションのインスタンスごとに、表 ( ) に 1 つの行があります。

たとえば、running:App[a].exeApp[b].exe

tblSequenceNos次のようになります。

iAppNo| iNextSequenceNo
  a   |     1234 
  b   |     4567

次のシーケンス番号を取得するためのストアド プロシージャは比較的単純です。

CREATE PROEDURE GetNextSequenceNo (@AppNo varchar(1), @NextSequenceNo int output)
AS
BEGIN
    DECLARE @TempSequenceNo int

    SELECT @NextSequenceNo = iNextSequenceNo 
    FROM tblSequenceNos 
    WHERE iAppNo = @AppNo

    @NextSequenceNo = @NextSequenceNo + 1

    UPDATE tblSequenceNos 
    SET iNextSequenceNo = @NextSequenceNo
    WHERE iAppNo = @AppNo

END

と の両方が値を取得するためにこの手順を実行しようとするとApp[a].exe、約 30 秒間ハングします (ADO タイムアウト?)。App[b].exeNextSequenceNo

各アプリはお互いの行を見ることがないので、特別な Locking を指定しなくても、これは同時に動作すると考えました。足りないものはありますか?テーブル全体やページではなく、行のみをロックするように指定する必要があるのではないかと思いましたか? - sql2008 のデフォルトの動作がわかりません。

どんな助けでも大歓迎です!前もってありがとう アンドリュー

4

1 に答える 1

2

プロシージャはスレッド セーフではなく、選択と更新の間で複数のスレッドが同じシーケンス番号を取得する可能性があるため、誤った結果が生成されます。

CREATE PROCEDURE GetNextSequenceNo (@AppNo varchar(1), @NextSequenceNo int output)
AS

 DECLARE @var table(seq int);

 UPDATE tblSequenceNos 
    SET iNextSequenceNo = @NextSequenceNo + 1
 OUTPUT inserted.iNextSequenceNo INTO @var;
  WHERE iAppNo = @AppNo

  select @NextSequenceNo = seq from @var
GO  

また、iAppNo 列がインデックス化されていることを確認してください。(これは、この列のみのインデックス、またはこのフィールドがインデックスの最初のフィールドであるインデックスを意味します)

于 2011-12-01T10:58:53.023 に答える