2010-12-31 18 views
7

SQL Server 2008 R2Serwer SQL (TSQL) - czy możliwe jest równoległe wykonywanie instrukcji EXEC?

Oto uproszczony przykład:

EXECUTE sp_executesql N'PRINT ''1st '' + convert(varchar, getdate(), 126) WAITFOR DELAY ''000:00:10''' 
EXECUTE sp_executesql N'PRINT ''2nd '' + convert(varchar, getdate(), 126)' 

Pierwsze sprawozdanie zostanie wydrukowana data i opóźnienie 10 sekund przed przejściem. Druga instrukcja powinna zostać wydrukowana natychmiast.

Sposób działania T-SQL, drugie oświadczenie nie zostanie ocenione przed pierwszym zakończeniem. Jeśli skopiuję go i wkleję do nowego okna zapytania, zostanie natychmiast wykonany.

Problem polega na tym, że mam inne, bardziej złożone rzeczy, ze zmiennymi, które muszą zostać przekazane do obu procedur.

Co staram się zrobić to:

  • Get rekord
  • zablokować go na pewien okres czasu
  • gdy jest zamknięty, należy wykonać kilka innych wypowiedzi przeciwko tej płycie i samej tabeli

Być może istnieje sposób, aby dynamicznie utworzyć kilka miejsc pracy?

W każdym razie, szukam prostego sposobu, aby to zrobić bez konieczności ręcznego drukowania instrukcji i kopiowania/wklejania do innej sesji.

Czy istnieje sposób na EXEC bez oczekiwania/równolegle?

+1

Dynamiczna technika zadania może działać dobrze w asynchronicznym wykonywaniu instrukcji SQL. –

Odpowiedz

2

Jeśli chcesz zablokować rekord, aby można było wykonywać wyciągi na jego podstawie, możesz wykonać te instrukcje jako transakcję.

Aby wykonać SQL równolegle, musisz paraleliować wywołania SQL, wykonując SQL z oddzielnych wątków/procesów w Javie, C++, perlu lub dowolnym innym języku programowania (hell, uruchamiając "isql" w skrypcie powłoki w tło zadziała)

15

Tak, jest sposób, zobacz Asynchronous procedure execution.

Jest jednak duża szansa, że ​​nie jest to potrzebne. T-SQL to język dostępu do danych , a gdy weźmie się pod uwagę transakcje, blokowanie i zatwierdzanie/wycofywanie semantyki jest niemożliwe niemożliwe do równoległego zadania. Równoległy T-SQL działa na przykład z requests queues, gdzie każde żądanie jest niezależne i nie ma korelacji między zadaniami.

To, co opisujesz, wcale nie brzmi tak, jak coś, co może, a nawet nie powinno, być paralelizowane.

+0

Podobnie jak uwaga, technika w łączu działa z powodu "Service Broker", który jest usługą wiadomości/kolejki w serwerze SQL. – DVK

+0

Powód do równoległego działania jest do celów testowych. Czasami przyczyną awarii jest dokładnie to, co chcesz osiągnąć. –

+1

Możesz uruchomić inny skrypt z pierwszego skryptu, poprzez 'sp_executesql' dla wykonania po stronie serwera lub używając rozszerzenia':! 'Sqlcmd (SSMS obsługuje je również po włączeniu) dla wykonania po stronie klienta. Jedną z komend, którą możesz uruchomić, jest 'start', który uruchomi proces i nie czeka na zakończenie. Więc możesz uruchomić 'sp_executesql 'start sqlcmd -E -S. -d nazwa_bazyny -i "myscript.sql" '; 'i osiągnąć" drugi wątek ". Dokładnie tak, jakby uruchamiał się z innego okna zapytania SSMS, ale jest zautomatyzowany. Jedna rzecz, którą stracisz, to jakikolwiek błąd/wynik ze skryptu, który zaczynasz. –

0

Jeśli po przeczytaniu wszystkich wyżej o potencjalnych problemach i nadal chcesz uruchomić rzeczy równolegle, to pewnie można spróbować sql pracy, umieścić swoje zapytania w różnych zadań, a następnie wykonać przez wywołanie ten sposób miejsc pracy

EXEC msdb..sp_start_job 'Job1' 

EXEC msdb..sp_start_job 'Job2' 
+0

Lub możesz po prostu uruchomić je w osobnych oknach zapytań. – Trisped

0

Zadania agenta SQL można uruchamiać równolegle i tworzyć bezpośrednio z TSQL.The answer by Remus Rusanu zawiera link, który wspomina o tym wraz z pewnymi wadami.

Inną wadą jest to, że do utworzenia pracy wymagane są dodatkowe uprawnienia zabezpieczeń. Ponadto, do realizacji poniżej, zadanie musi działać jako konkretny użytkownik + login z dodatkowymi uprawnieniami do zarządzania pracą.

Możliwe jest uruchomienie arbitralnego SQL'a jako innego (bezpieczniejszego) użytkownika, ale uważam, że wymaga ono uprawnień sysadmin do oznaczenia pracy jako takiej.

Zwróconego @ pJobIdHexOut można użyć do zatrzymania zadania, jeśli jest to konieczne.

create proc [Common].[usp_CreateExecuteOneTimeBackgroundJob] 
    @pJobNameKey   varchar(100),  -- Caller should ensure uniqueness to avoid a violation 
    @pJobDescription  varchar(1000), 
    @pSql     nvarchar(max), 
    @pJobIdHexOut   varchar(100) = null out, -- JobId as Hex string. For SqlServer 2014 binary(16) = varchar(64) 
    @pDebug    bit = 0 -- True to include print messages 
-- 
with execute as 'TSqlBackgroundJobOwner' -- requires special permissions (See below) 
as 
/*--------------------------------------------------------------------------------------------------------------------- 
    Purpose: Create a one time background job and launch it immediately. The job is owned by the "execute as" UserName 

       Caller must ensure the @pSql argument is safe. 

Required Permissions for "execute as" user: 

     -- User must be created with associated login (w/ deny connect). 

     use [msdb]; 
     create user [$UserName$] for login [$LoginName$]; 
     alter role [SQLAgentUserRole] add member [$UserName$]; 
     alter role [SQLAgentReaderRole] add member [$UserName$]; 
     alter role [SQLAgentOperatorRole] add member [$UserName$]; 
     grant select on dbo.sysjobs to [$UserName$]; 
     grant select on dbo.sysjobactivity to [$UserName$];', 

     use [Master]; 
     create user [$UserName$] for login [$LoginName$]; 
     grant execute on xp_sqlagent_is_starting to [$UserName$]; 
     grant execute on xp_sqlagent_notify to [$UserName$];'; 


    Modified By   Description 
    ---------- ----------- ------------------------------------------------------------------------------------------ 
    2014.08.22 crokusek  Initial version 
    2015.12.22 crokusek  Use the SP caller as the job owner (removed the explicit setting of the job owner). 
    ---------------------------------------------------------------------------------------------------------------------*/ 
begin try  

    declare 
     @usp     varchar(100) = object_name(@@procid), 
     @currentDatabase  nvarchar(100) = db_name(), 
     @jobId    binary(16),   
     @jobOwnerLogin  nvarchar(100); 

    set xact_abort on; -- ensure transaction is aborted on non-catchables like client timeout, etc. 
    begin transaction 

     exec msdb.dbo.sp_add_job 
      @[email protected], 
       @enabled=1, 
       @notify_level_eventlog=0, 
       @notify_level_email=2, 
       @notify_level_netsend=2, 
       @notify_level_page=2, 
       @delete_level=3, 
       @[email protected], 
       @category_name=N'Database Maintenance', 
      -- If not overridden then the the current login is the job owner 
      [email protected][email protected], -- Requires sysadmin to set this so avoiding. 
      @job_id = @jobId output; 

     -- Get the job_id string of the jobId (special format) 
     -- 
     set @pJobIdHexOut = Common.ufn_JobIdFromHex(@jobId); 

     if (@pDebug = 1) 
     begin 
      print 'JobId: ' + @pJobIdHexOut; 
      print 'Sql: ' + @pSql; 
     end 

     exec msdb.dbo.sp_add_jobserver @[email protected]; -- default is local server 

     exec msdb.dbo.sp_add_jobstep 
      @[email protected], 
      @step_name=N'One-Time Job Step 1', 
       @step_id=1, 
      @[email protected], 
       @[email protected], 
       @cmdexec_success_code=0, 
       @on_success_action=1, 
       @on_fail_action=2, 
       @retry_attempts=0, 
       @retry_interval=0, 
       @os_run_priority=0, 
      @subsystem=N'TSQL', 
       @flags=0 
      ; 

      declare 
       @startResult int;      

      exec @startResult = msdb.dbo.sp_start_job 
       @job_id = @jobId; 

     -- End the transaction 
     -- 
     if (@startResult != 0)   
      raiserror('Unable to start the job', 16, 1); -- causes rollback in catch block 
     else 
      commit; -- Success 

end try 
begin catch 
    declare   
     @CatchingUsp varchar(100) = object_name(@@procid);  

    if (xact_state() = -1) 
     rollback; 

    --exec Common.usp_Log 
    -- @pMethod = @CatchingUsp; 

    --exec Common.usp_RethrowError 
    -- @pCatchingMethod = @CatchingUsp; 
end catch 
Powiązane problemy