Tôi có thể khởi chạy một thủ tục được lưu trữ và ngay lập tức quay lại mà không cần đợi nó kết thúc không?


41

Chúng tôi có một quy trình được lưu trữ mà người dùng có thể chạy thủ công để nhận một số số cập nhật cho báo cáo được sử dụng liên tục trong cả ngày.

Tôi có một thủ tục được lưu trữ thứ hai nên được chạy sau khi thủ tục được lưu trữ đầu tiên chạy vì nó dựa trên các số thu được từ thủ tục được lưu trữ đầu tiên này, tuy nhiên phải mất nhiều thời gian hơn để chạy và là một quy trình riêng biệt, vì vậy tôi không muốn làm cho người dùng chờ trong khi thủ tục lưu trữ thứ 2 này được chạy.

Có cách nào để có một thủ tục được lưu trữ bắt đầu một thủ tục được lưu trữ thứ hai và quay lại ngay lập tức mà không cần chờ kết quả không?

Tôi đang sử dụng SQL Server 2005.


Làm thế nào là các thủ tục lưu trữ được gọi là? Ứng dụng web ASP.NET? SSRS?
Mr.Brownstone


@ Mr.Brownstone Nó thường được gọi từ một ứng dụng web ASP.Net, mặc dù nó có thể được gọi bởi nhiều người trong số họ. Tôi phải kiểm tra lại. Nó cũng thỉnh thoảng được chạy thủ công từ SSRS.
Rachel

@MartinSmith Tôi đã từng làm việc với nhà môi giới dịch vụ SQL trong quá khứ và hy vọng sẽ có một cách đơn giản hơn. Có vẻ như một thiết lập phức tạp cho một cái gì đó đơn giản như thế này.
Rachel

1
@MartinSmith đó là khá nhiều những gì tôi đã nghĩ - cũng như đối với SSRS, bạn không thể làm gì ngoài việc kết hợp Trình xem Báo cáo vào ứng dụng và di chuyển lệnh của bạn vào đó - theo cách đó có thể thực hiện các cuộc gọi không đồng bộ cho các báo cáo là tốt.
Mr.Brownstone

Câu trả lời:


27

Có vẻ như có nhiều cách để thực hiện điều này, nhưng tôi thấy cách đơn giản nhất là gợi ý của Martin về việc thiết lập thủ tục trong công việc SQL và bắt đầu bằng cách sử dụng lệnh sp_start_job không đồng bộ từ quy trình được lưu trữ của tôi.

EXEC msdb.dbo.sp_start_job @job_name='Run2ndStoredProcedure'

Điều này chỉ hoạt động với tôi vì tôi không cần chỉ định bất kỳ tham số nào cho quy trình được lưu trữ của mình.

Các đề xuất khác có thể hoạt động tùy thuộc vào tình huống của bạn là

  • Sử dụng Nhà môi giới dịch vụ SQL như MartinSebastian đề xuất. Đây có lẽ là gợi ý tốt nhất nếu bạn không bận tâm đến sự phức tạp của việc thiết lập và tìm hiểu cách thức hoạt động của nó.
  • Chạy quy trình không đồng bộ trong mã chịu trách nhiệm thực thi thủ tục được lưu trữ, như Mr.Brownstone đề xuất .

    Không phải là một ý tưởng tồi, tuy nhiên trong trường hợp của tôi, thủ tục được lưu trữ được gọi từ nhiều nơi, vì vậy việc tìm tất cả những nơi đó và đảm bảo họ gọi thủ tục thứ 2 cũng không thực tế. Ngoài ra, quy trình lưu trữ thứ 2 khá quan trọng và việc quên chạy nó có thể gây ra một số vấn đề lớn cho công ty chúng tôi.

  • Đặt thủ tục đầu tiên đặt cờ và thiết lập công việc định kỳ để kiểm tra cờ đó và chạy nếu được đặt, như Jimbo đề xuất . Tôi không phải là một fan hâm mộ lớn của các công việc chạy liên tục và kiểm tra các thay đổi cứ sau vài phút, nhưng chắc chắn đó là một lựa chọn đáng để xem xét tùy thuộc vào tình huống của bạn.

3
Hãy xem Thực thi thủ tục không đồng bộ để biết ví dụ sẵn sàng sử dụng bằng cách sử dụng Nhà môi giới dịch vụ. Ưu điểm của sp_job là nó hoạt động trên Express Edition và hoàn toàn chứa DB (không phụ thuộc vào bảng công việc MSDB). Cái sau này rất quan trọng trong chuyển đổi dự phòng DBM và phục hồi HA / DR.
Remus Rusanu

Bắn, tôi thấy Martin liên kết cùng một bài viết. Tôi sẽ để lại nhận xét cho các đối số failover / DR.
Remus Rusanu

@RemusRusanu: tốt, đó là một trong những nguồn thông tin tốt nhất liên quan đến Nhà môi giới dịch vụ, nhưng tôi cho rằng bạn đã biết rồi ;-).
Mary

Tôi thích liên kết từ @Rusanu, nhưng tôi muốn một cái gì đó không có phản hồi (mà tôi nghĩ phù hợp với vấn đề này). Tôi đã viết lên phiên bản đơn giản hóa của mình tại abamacus.blogspot.com/2016/05/ Khăn
Bàn tính

Ngoài ra, nếu bạn cố gắng bắt đầu một công việc Đại lý SQL, nó sẽ thất bại với EXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'.Nhà môi giới dịch vụ hoặc Đại lý Sql, không tồn tại trên Azure. Tôi không biết tại sao Microsoft, sau một thập kỷ rưỡi người hỏi, từ chối thêm EXECUTE ASYNC RematerializeExpensiveCacheTable.
Ian Boyd

8

Bạn có thể sử dụng dịch vụ môi giới cùng với kích hoạt trên hàng đợi. Với điều đó bạn có thể đăng các tham số cho cuộc gọi thủ tục trên hàng đợi. Điều đó mất khoảng nhiều thời gian như một chèn. Sau khi giao dịch được cam kết và có khả năng thêm vài giây nữa, kích hoạt sẽ tự động gọi thủ tục người nhận không đồng bộ. Nó chỉ hơn là phải lấy các tham số của hàng đợi và thực hiện công việc mong muốn.


7

Câu hỏi cũ này xứng đáng có một câu trả lời toàn diện hơn. Một số trong số này được đề cập trong các câu trả lời / nhận xét khác ở đây, một số khác có thể hoặc không hoạt động cho tình huống cụ thể của OP, nhưng có thể hoạt động cho những người khác đang tìm cách gọi các procs được lưu trữ không đồng bộ từ SQL.

Hoàn toàn rõ ràng: TSQL không (tự nó) có khả năng khởi chạy các hoạt động TSQL khác không đồng bộ .

Điều đó không có nghĩa là bạn vẫn không có nhiều lựa chọn:

  • Các công việc của Tác nhân SQL : Tạo nhiều công việc SQL và lên lịch cho chúng chạy vào thời gian mong muốn hoặc khởi động chúng không đồng bộ từ một "điều khiển chính" được lưu trữ bằng cách sử dụng sp_start_job. Nếu bạn cần theo dõi tiến trình của họ theo chương trình, chỉ cần đảm bảo mỗi công việc cập nhật bảng JOB_PROGRESS tùy chỉnh (hoặc bạn có thể kiểm tra xem họ đã hoàn thành chưa sử dụng chức năng không có giấy tờ xp_sqlagent_enum_jobsnhư được mô tả trong bài viết xuất sắc này của Gregory A. Larsen). Bạn phải tạo nhiều công việc riêng biệt như bạn muốn các quy trình song song đang chạy, ngay cả khi chúng đang chạy cùng một Proc được lưu trữ với các tham số khác nhau.
  • Gói SSIS : Đối với các kịch bản không đồng bộ phức tạp hơn, hãy tạo gói SSIS với luồng tác vụ phân nhánh đơn giản. SSIS sẽ khởi chạy các tác vụ đó trong các spids riêng lẻ mà SQL sẽ thực thi song song. Gọi gói SSIS từ một công việc đại lý SQL.
  • Ứng dụng tùy chỉnh : Viết một ứng dụng tùy chỉnh đơn giản bằng ngôn ngữ bạn chọn (C #, Powershell, v.v.), sử dụng các phương thức không đồng bộ được cung cấp bởi ngôn ngữ đó. Gọi một SQL được lưu trữ trên mỗi luồng ứng dụng.
  • Tự động hóa OLE : Trong SQL, sử dụng sp_oacreatesp_oamethodđể khởi chạy một quy trình mới gọi nhau là Proc được lưu trữ như được mô tả trong bài viết này , cũng bởi Gregory A. Larsen.
  • Nhà môi giới dịch vụ : Xem xét việc sử dụng Nhà môi giới dịch vụ , một ví dụ điển hình về thực thi không đồng bộ trong bài viết này .
  • Thực thi song song CLR : Sử dụng các lệnh CLR Parallel_AddSqlParallel_Executenhư được mô tả trong bài viết này của Alan Kaplan (chỉ SQL2005 +).
  • Các tác vụ Windows được lên lịch : Được liệt kê để hoàn thiện, nhưng tôi không phải là người hâm mộ của tùy chọn này.

Nếu là tôi, có lẽ tôi sẽ sử dụng nhiều Công việc Tác nhân SQL trong các tình huống đơn giản hơn và gói SSIS trong các tình huống phức tạp hơn.

Trong trường hợp của bạn, việc gọi các tác nhân SQL Agent nghe có vẻ như là một lựa chọn đơn giản và dễ quản lý.

Một nhận xét cuối cùng : SQL đã cố gắng song song hóa các hoạt động riêng lẻ bất cứ khi nào có thể *. Điều này có nghĩa là chạy 2 nhiệm vụ cùng một lúc thay vì sau nhau không đảm bảo rằng nó sẽ hoàn thành sớm hơn. Kiểm tra cẩn thận để xem liệu nó thực sự cải thiện bất cứ điều gì hay không.

Chúng tôi đã có một nhà phát triển tạo ra gói DTS để chạy 8 tác vụ cùng một lúc. Thật không may, nó chỉ là một máy chủ 4 CPU :)

* Giả sử cài đặt mặc định. Điều này có thể được sửa đổi bằng cách thay đổi Mức độ song song hoặc Mặt nạ tối đa của máy chủ hoặc bằng cách sử dụng gợi ý truy vấn MAXDOP.


6

Có, một phương pháp:

  1. Khi thủ tục được lưu trữ thứ 1 hoàn tất, nó sẽ chèn một bản ghi với tất cả thông tin cần thiết cho quy trình được lưu trữ thứ hai để chạy
  2. Thủ tục lưu trữ thứ hai chạy như một công việc, mỗi phút hoặc thời gian bạn quyết định
  3. Nó kiểm tra các bản ghi được chèn, thực hiện quá trình của nó và đánh dấu bản ghi là hoàn thành

Điều này giới hạn việc thực thi thủ tục được lưu trữ đối với số lượng công việc bạn đang chạy mà nếu bạn chỉ muốn một ứng dụng này được gọi bởi một khách hàng tại một thời điểm thì tốt - trong khi bạn có thể có nhiều khách hàng gọi cùng một quy trình cùng một lúc . Ngoài ra, làm thế nào để khách hàng biết công việc đã hoàn thành mà không cần thăm dò cơ sở dữ liệu nhiều lần để tìm hiểu xem một cờ đã được đặt chưa?
Mr.Brownstone

1
@ Mr.Brownstone - Có khả năng công việc có thể xử lý nhiều hơn một nhiệm vụ nổi bật được xếp hàng bởi các lệnh gọi thủ tục được lưu trữ khác nhau khi nó chạy. Thủ tục được lưu trữ cũng có thể có thể gọi sp_start_jobđể bắt đầu hoặc tạo công việc khi cần thiết để tránh bỏ phiếu mỗi phút nhưng sự phức tạp trong trường hợp đó có lẽ có nghĩa là nó sẽ không đơn giản hơn nhà môi giới dịch vụ.
Martin Smith

@MartinSmith Tôi thực sự đã có một thiết lập công việc cho quy trình được lưu trữ thứ 2 này vì nó được sử dụng hàng đêm cho đến khi chúng tôi thấy một số vấn đề với nó không được đồng bộ hóa chính xác với các số của quy trình 1. Nếu tôi bắt đầu công việc từ thủ tục được lưu trữ thứ 1, nó có chạy không đồng bộ và trở về từ SP ngay lập tức không?
Rachel

@Rachel - Vâng. sp_start_jobtrả lại ngay lập tức Không thể nhớ những quyền mà nó cần mặc dù.
Martin Smith

1
Bắt đầu một công việc từ một thủ tục / cơ sở dữ liệu khác là một vấn đề khá phức tạp nếu bạn không muốn mở ra những lỗ hổng bảo mật lớn. Erland Sommarskog có một bài viết về các kỹ thuật khác nhau mà bạn cần kết hợp: sommarskog.se/grantperm.html Tuy nhiên, không có giải pháp hoàn chỉnh nào trong đó.
Sebastian Meine

1

Một khả năng khác là lấy thủ tục được lưu trữ thứ nhất để ghi vào bảng kiểm toán khi nó hoàn thành và đặt một trình kích hoạt trên bảng kiểm toán khởi chạy thủ tục được lưu trữ thứ 2 khi bảng kiểm toán được ghi vào. Không cần phải thăm dò liên tục và không cần thêm một công việc SQL Server Agent.


3
Quy trình được lưu trữ đầu tiên sẽ không quay trở lại cho đến khi quá trình chèn vào bảng kiểm toán hoàn tất và điều đó sẽ không xảy ra cho đến khi trình kích hoạt kết thúc thực hiện (bao gồm cả lệnh gọi đến quy trình được lưu trữ thứ 2)
Martin Smith

1
Tôi đã xem xét việc sử dụng Trình kích hoạt, nhưng các trình kích hoạt được chạy đồng bộ với câu lệnh INSERThoặc UPDATE, không đồng bộ, vì vậy Martin đã đúng rằng quy trình đầu tiên vẫn sẽ đợi cho đến khi thủ tục thứ 2 kết thúc để trả về.
Rachel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.