2

実行中SQL Server 2014。グローバル一時テーブルにデータを書き込む必要があるストアド プロシージャがあります。ただし、OBJECT_IDプロシージャがトランザクション内で呼び出されると、メソッドがハングするようです。

トランザクションを削除せずにデッドロックを削除するにはどうすればよいですか?

ストアド プロシージャ:

CREATE PROCEDURE [dbo].[foo]
    @Data [varbinary](max)
WITH ENCRYPTION AS
BEGIN
    SET NOCOUNT ON

    IF OBJECT_ID('tempdb..##TempData') IS NULL
        CREATE TABLE ##TempData
        (
            [ID] [int] IDENTITY(1,1) NOT NULL,
            [Data] [int] NOT NULL UNIQUE
        )

    INSERT INTO ##TempData ([Data]) SELECT @Data
END
GO

最初の接続:

BEGIN TRAN
EXEC [foo] @Data = 1
WAITFOR DELAY '00:00:20'
COMMIT TRAN

DROP TABLE ##TempData

次に、2番目の接続で:

BEGIN TRAN
EXEC [foo] @Data = 2 -- This will hang on the call to OBJECT_ID()...
COMMIT TRAN

アップデート

C#トランザクションが必要な理由を示すコードを次に示します。

var options = new TransactionOptions();
// options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TransactionManager.MaximumTimeout;

using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
    // Write to ##TempData. Lengthy operation...
    var foo = Foo(data);

    // These two MUST be inside a transaction!
    var bar = Bar();
    var baz = Baz(); // Consume data in ##TempData

    transaction.Complete();
}
4

1 に答える 1

2

(うまくいけば、これはあなたの問題を解決するための別の潜在的な方法になるでしょう...コメントするには長すぎます)

コメントにあったことに加えて、実際のテーブルを使用すると、やろうとしていることを少し簡単に実行できるようになると思います (ただし、それがまだ何であるかは少しわかりません)。

このような方法でテーブルを作成した場合:

create table tmpDataThingy (
    connectionUniqueId uniqueIdentifier,
    someOtherColumn int,
    andYetAnother varchar(50)
)

この方法でテーブル (重要な部分はconnectionUniqueId) を作成すると、テーブル内のデータを操作するときに「作業単位」(おそらく適切な言葉ではない) を追跡できます。

using ステートメントは次のようになります。

using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
    Guid uniqueId = Guid.NewGuid(); // consider this a "session" identifier for a single instance of the work needed for this call

    // insert your data into tmpDataThingy ensuring connectionUniqueId = uniqueId (the guid created above)
    // consume/manipulate data in tmpDataThingy only for the specified uniqueId
    // remove data from tmpDataThingy for the uniqueId

    transaction.Complete();
}

上記を実行すると、テーブルが存在しないという潜在的な問題は発生しません。関数の呼び出しごとに異なる方法で生成される uniqueId が原因で、競合するデータを使用して複数のユーザーが同じ関数を呼び出す可能性もありません。

于 2015-07-22T12:59:46.010 に答える