2010-12-31 45 views
7

SQL Server 2008 R2SQL Server (TSQL) - Có thể cho các câu lệnh EXEC song song không?

Đây là một ví dụ đơn giản:

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)' 

Bản tuyên bố đầu tiên sẽ in ngày và làm chậm 10 giây trước khi tiếp tục. Câu lệnh thứ hai sẽ in ngay lập tức.

Cách T-SQL hoạt động, câu lệnh thứ 2 sẽ không được đánh giá cho đến khi lần hoàn thành đầu tiên. Nếu tôi sao chép và dán nó vào một cửa sổ truy vấn mới, nó sẽ thực thi ngay lập tức.

Vấn đề là tôi có những thứ khác, phức tạp hơn đang xảy ra, với các biến cần được chuyển cho cả hai thủ tục.

Những gì tôi đang cố gắng làm là:

  • Nhận một kỷ lục
  • Khóa nó cho một khoảng thời gian
  • trong khi nó đang bị khóa, thực hiện một số báo cáo khác chống lại hồ sơ này và bảng riêng của mình

Có thể có cách để tự động tạo một vài công việc?

Dù sao, tôi đang tìm một cách đơn giản để thực hiện việc này mà không cần phải viết câu lệnh PRINT theo cách thủ công và sao chép/dán sang phiên khác.

Có cách nào để EXEC mà không cần chờ/song song không?

+1

Kỹ thuật công việc động có thể hoạt động tốt để thực thi SQL không đồng bộ. –

Trả lời

2

Nếu bạn muốn khóa bản ghi để có thể thực hiện các câu lệnh chống lại nó, bạn có thể muốn thực hiện các câu lệnh đó dưới dạng giao dịch. Để thực thi SQL song song, bạn cần phải so sánh các cuộc gọi SQL, bằng cách thực thi SQL của bạn từ bên trong các luồng/quy trình riêng biệt trong Java, C++, perl, hoặc bất kỳ ngôn ngữ lập trình nào khác (địa ngục, khởi chạy "isql" trong kịch bản lệnh shell trong). nền sẽ hoạt động)

15

Có, có một cách, xem Asynchronous procedure execution.

Tuy nhiên, rất có thể đây không phải là những gì bạn cần. T-SQL là một ngôn ngữ truy cập dữ liệu và khi bạn xem xét các giao dịch, khóa và ngữ nghĩa cam kết/rollback gần như không thể để có công việc song song. T-SQL song song hoạt động ví dụ với requests queues, trong đó mỗi yêu cầu độc lập và không có sự tương quan giữa các công việc.

Những gì bạn mô tả không có vẻ gì giống như thứ gì đó có thể, và cũng không nên thực sự được so sánh.

+0

Cũng giống như một lưu ý, kỹ thuật trong liên kết hoạt động do "Nhà môi giới dịch vụ", là dịch vụ nhắn tin/xếp hàng trong máy chủ SQL. – DVK

+0

Lý do để song song nó là dành cho mục đích thử nghiệm. Đôi khi, gây ra lỗi là chính xác những gì bạn muốn đạt được. –

+1

Bạn có thể chạy tập lệnh khác từ tập lệnh đầu tiên, thông qua 'sp_executesql' để thực thi phía máy chủ hoặc sử dụng phần mở rộng':! 'Sqlcmd (SSMS cũng hỗ trợ chúng khi được bật) để thực thi phía máy khách. Một lệnh bạn có thể chạy là 'bắt đầu', lệnh này sẽ khởi chạy một tiến trình và không đợi để hoàn thành. Vì vậy, bạn có thể chạy 'sp_executesql 'bắt đầu sqlcmd -E -S. -d dbname -i "myscript.sql" '; 'và đạt được' chuỗi thứ hai '. Chính xác như thể chạy từ một cửa sổ truy vấn SSMS khác, nhưng tự động. Một điều bạn sẽ mất là bất kỳ lỗi/kết quả nào từ tập lệnh bạn bắt đầu. –

0

Nếu sau khi đọc bài ở trên về vấn đề tiềm năng và bạn vẫn muốn chạy thứ song song, có lẽ bạn có thể thử việc sql, đặt câu hỏi của bạn trong công việc khác nhau, sau đó thực hiện bằng cách gọi các công việc như thế này

EXEC msdb..sp_start_job 'Job1' 

EXEC msdb..sp_start_job 'Job2' 
+0

Hoặc bạn chỉ có thể chạy chúng trong các cửa sổ truy vấn riêng biệt. – Trisped

0

Nó có thể là giá trị để kiểm tra bài viết Asynchronous T-SQL Execution Without Service Broker.

+2

Tôi không phản đối khi bình luận của tôi bị hạ cấp. Nhưng tôi nhớ nếu điều này được thực hiện mà không cần giải thích. –

0

Tác vụ của tác nhân SQL có thể chạy song song và được tạo trực tiếp từ TSQL.Các answer by Remus Rusanu chứa một liên kết đề cập đến điều này cùng với một số nhược điểm.

Một bất lợi khác là các quyền bảo mật bổ sung được yêu cầu để tạo công việc. Ngoài ra, để thực hiện dưới đây, công việc phải chạy như một người dùng cụ thể + đăng nhập với các đặc quyền quản lý công việc bổ sung.

Có thể chạy SQL tùy ý với tư cách người dùng khác (an toàn hơn) tuy nhiên tôi tin rằng nó yêu cầu đặc quyền sysadmin chỉ định công việc như vậy.

Trả về @pJobIdHexOut có thể được sử dụng để dừng công việc nếu cần.

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 
Các vấn đề liên quan