T-SQL의 슬립 명령?


364

일정 시간 동안 절전 모드로 전환하기 위해 T-SQL 명령을 작성해야합니까? 웹 서비스를 비동기 적으로 작성하고 있으며 비동기 패턴이 실제로 확장 성을 높이기 위해 몇 가지 테스트를 실행할 수 있기를 원합니다. 느린 외부 서비스를 "모의"하기 위해 느리게 실행되지만 실제로는 많은 것을 처리하지 않는 스크립트로 SQL 서버를 호출 할 수 있기를 원합니다.


19
공정한 질문! 언젠가 이것을 사용하고 싶을 수도 있습니다. 완전히 제쳐두고, 이것은 내가 DB를 느리게하고 싶다고 들었을 때 처음으로 들었다.)
p.campbell

2
T-SQL에서 비동기 서비스를 호출하여 혼란에 빠졌습니다.
jmucchiello

답변:


616

상기 봐 WAITFOR의 명령.

예 :

-- wait for 1 minute
WAITFOR DELAY '00:01'

-- wait for 1 second
WAITFOR DELAY '00:00:01'

이 명령은 높은 정밀도를 허용하지만 GetTickCount에 의존하기 때문에 일반적인 컴퓨터에서는 10ms-16ms 내에서만 정확 합니다 . 예를 들어, 통화 는 전혀 기다리지 않을 것입니다.WAITFOR DELAY '00:00:00:001'


4
아무도 이것을 함수에서 작동시키는 방법을 알고 있습니까? 나는 (아마 제대로) 얻을,하지만 난) 재정에 함수 내에서 WAITFOR ''사이드 초래 운영자의 잘못된 사용 '을 원하는 테스트를 위해서 ....에 대한
monojohnny

2
@monojohnny가 SVF를 기다리려면 아래에서 Josh의 답변을 시도했지만 작동하지 않았습니다. 대신 다음과 같이 WHILE 루프를 만듭니다.CREATE FUNCTION [dbo].[ForcedTimeout](@seconds int) returns int as BEGIN DECLARE @endTime datetime2(0) = DATEADD(SECOND, @seconds, GETDATE()); WHILE (GETDATE() < @endTime ) BEGIN SET @endTime = @endTime; -- do nothing, but SQL requires a statement. END
GilesDMiddleton

3
ms에 3 자리 숫자를 사용해야합니다. '00 : 00 : 00 : 01 '은 '00 : 00 : 00 : 010'과 같지 않습니다. 두 번째는 사용하십시오. (MSSQL 2016에서 테스트)
Nick

테이블을 차단해야하는 경우 BEGIN TRANSACTION 및 END TRANSACTION을 시도 할 수도 있습니다.
Richárd Baldauf

9
WAITFOR DELAY 'HH:MM:SS'

이것이 기다릴 수있는 최대 시간은 23 시간 59 분 59 초라고 생각합니다.

스칼라 값 함수는 다음과 같습니다. 아래 함수는 초의 정수 매개 변수를 취한 다음 HH : MM : SS로 변환 EXEC sp_executesql @sqlcode하고 쿼리 명령을 사용하여 실행합니다. 아래 함수는 데모 용입니다. 스칼라 값 함수로 실제로는 적합하지 않습니다! :-)

    CREATE FUNCTION [dbo].[ufn_DelayFor_MaxTimeIs24Hours]
    (
    @sec int
    )
    RETURNS
    nvarchar(4)
    AS
    BEGIN


    declare @hours int = @sec / 60 / 60
    declare @mins int = (@sec / 60) - (@hours * 60)
    declare @secs int = (@sec - ((@hours * 60) * 60)) - (@mins * 60)


    IF @hours > 23 
    BEGIN
    select @hours = 23
    select @mins = 59
    select @secs = 59
    -- 'maximum wait time is 23 hours, 59 minutes and 59 seconds.'
    END


    declare @sql nvarchar(24) = 'WAITFOR DELAY '+char(39)+cast(@hours as nvarchar(2))+':'+CAST(@mins as nvarchar(2))+':'+CAST(@secs as nvarchar(2))+char(39)


    exec sp_executesql @sql

    return ''
    END

24 시간 이상 지연하려면 @Days 매개 변수를 사용하여 며칠 동안 가고 함수 실행 파일을 루프 안에 넣는 것이 좋습니다.

    Declare @Days int = 5
    Declare @CurrentDay int = 1

    WHILE @CurrentDay <= @Days
    BEGIN

    --24 hours, function will run for 23 hours, 59 minutes, 59 seconds per run.
    [ufn_DelayFor_MaxTimeIs24Hours] 86400

    SELECT @CurrentDay = @CurrentDay + 1
    END

SQL Azure 는이 Only functions and some extended stored procedures can be executed from within a function. 문서가 마음에 들지 않습니다. MS Docs는 Stored Procs를 사용한 예제를 제공합니다. 이 방법이 잘못된 것 같습니다
SliverNinja-MSFT

5

"시간"을 "대기"할 수도 있습니다.

    RAISERROR('Im about to wait for a certain time...', 0, 1) WITH NOWAIT
    WAITFOR TIME '16:43:30.000'
    RAISERROR('I waited!', 0, 1) WITH NOWAIT

2
PRINT대신에 사용 하지 RAISERROR않겠습니까?
slartidan

4
그렇지 않으면 전체 대기가 끝날 때까지 아무것도 볼 수 없기 때문입니다. RAISERROR는 NOWAIT 옵션을 제공하므로 버퍼가 가득 찼을 때 또는 배치가 완료된 후가 아니라 실시간으로 인쇄 문을 (필수적으로) 표시합니다.
Jeremy Giaco

0

다음은 CommandTimeout을 테스트하기위한 매우 간단한 C # 코드입니다. 새로운 명령을 생성하여 2 초 동안 기다립니다. CommandTimeout을 1 초로 설정하면 실행할 때 예외가 표시됩니다. CommandTimeout을 0 또는 2보다 높은 값으로 설정하면 정상적으로 실행됩니다. 그런데 기본 CommandTimeout은 30 초입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.SqlClient;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
      var builder = new SqlConnectionStringBuilder();
      builder.DataSource = "localhost";
      builder.IntegratedSecurity = true;
      builder.InitialCatalog = "master";

      var connectionString = builder.ConnectionString;

      using (var connection = new SqlConnection(connectionString))
      {
        connection.Open();

        using (var command = connection.CreateCommand())
        {
          command.CommandText = "WAITFOR DELAY '00:00:02'";
          command.CommandTimeout = 1;

          command.ExecuteNonQuery();
        }
      }
    }
  }
}

2
c #에 있다면 아마도 동일한 작업을 수행하는 Thread.currentThread.sleep (60000) 또는 Thread.sleep (60000)을 사용해야합니다. 이렇게하면 지연이 애플리케이션에 격리됩니다. 그런 다음 후속 데이터베이스 로직을 호출하십시오.
액션 Dan

2
@ActionDan Thread.Sleep을 사용하면 CommandTimeout을 실행하는 데 도움이되지 않습니다. 고안된 예로서 상자에 쓰여진 내용을 수행합니다.
Richard Hauer 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.