web-dev-qa-db-ja.com

SET LOCK_TIMEOUTを使用してストアドプロシージャを実行する

とにかくSET LOCK_TIMEOUTでストアドプロシージャを明示的に実行する方法はありますか?

例えば。 dbo.LoadDataというsprocがあります。テーブルdbo.Abcからデータを取得し、テーブルdbo.Xyzに挿入するだけです。

ここで、sproc dbo.LoadDataを実行したいのですが、テーブルdbo.Abclockedの場合、 10秒を超える場合は、ストアドプロシージャの実行を停止します。

オプションSET LOCK_TIMEOUTはsproc dbo.LoadData自体に実装できることは知っていますが、明示的に呼び出す方法があるかどうか(=ストアドプロシージャ自体にオプションを実装していない)。

3
DNac

LOCK_TIMEOUTは、セッションレベルの設定であるだけでなく、別のバッチで設定する必要もあります。ただし、変数を介して設定することはできません。したがって、これは、「マスター」ストアドプロシージャで動的SQLを使用することで実現できます。これにより、LOCK_TIMEOUT次に、この特定の設定内で実行する必要がある他のストアドプロシージャを実行します。設定は最上位/最外部のプロセスの値に戻るため、動的SQLを1回実行する必要があります。例えば:

これをSSMSの1つのクエリタブで実行します。

GO
CREATE PROCEDURE ##ShouldTimeout
AS
INSERT INTO ##LockedTable ([ID]) VALUES (1);
GO


GO
CREATE PROCEDURE ##TimeoutTest
(
    @SecondsUntilTimeout INT = 2
)
AS
SET NOCOUNT ON;

SET @SecondsUntilTimeout = ISNULL(@SecondsUntilTimeout, 2); -- enforce default

DECLARE @SQL NVARCHAR(MAX) = N'SET LOCK_TIMEOUT ';
SET @SQL += CONVERT(NVARCHAR(MAX), @SecondsUntilTimeout * 1000) + N';
';

SET @SQL += N'EXEC ##ShouldTimeout;'; -- use CASE / IF to decide what to exec

RAISERROR(@SQL, 10, 1) WITH NOWAIT; -- print Dynamic SQL in "Messages" tab

EXEC (@SQL);
GO

SSMSの別のクエリタブで次を実行します。

BEGIN TRAN;
CREATE TABLE ##LockedTable (ID INT);

-- ROLLBACK

次に、最初のクエリタブ(2つの一時ストアドプロシージャを作成した場所)に戻り、次の2つのテストを実行します。

EXEC ##TimeoutTest;
-- this will timeout after 2 seconds (the default)


EXEC ##TimeoutTest 5;
-- this will timeout after 5 seconds

次に、2番目のクエリタブに戻り、ROLLBACK ;-)を実行します。

3
Solomon Rutzky

いいえ、それはできません。これは接続のプロパティです。

オンライン書籍:

接続の開始時、この設定の値は-1です。変更後、新しい設定は残りの接続で有効になります。 SET LOCK_TIMEOUTの設定は、実行時または実行時に設定され、解析時ではありません。

それがどのように使用できるかのいくつかの例と議論:

  1. SET LOCK_TIMEOUT、それはセッションまたはステートメントベースですか?
  2. https://blog.sqlauthority.com/2013/01/28/sql-server-basic-explanation-of-set-lock_timeout-how-to-not-wait-on-locked-query/ =
  3. LOCK_TIMEOUTをインスタンス全体またはデータベース全体に設定できますか?
1
SqlWorldWide