Tạo một công việc chấm dứt nếu nó không được thực hiện trên bản sao chính
Trong trường hợp này, mọi công việc trên cả hai máy chủ đều cần một trong hai đoạn mã sau đây như Bước 1:
Kiểm tra theo tên nhóm:
IF master.dbo.svf_AgReplicaState('my_group_name')=0
raiserror ('This is not the primary replica.',2,1)
Kiểm tra theo tên cơ sở dữ liệu:
IF master.dbo.svf_AgReplicaState('my_db_name')=0
raiserror ('This is not the primary replica.',2,1)
Nếu bạn sử dụng cái thứ hai này, hãy cẩn thận với cơ sở dữ liệu hệ thống - theo định nghĩa, chúng không thể là một phần của bất kỳ nhóm khả dụng nào, vì vậy nó sẽ luôn thất bại đối với những cơ sở dữ liệu đó.
Cả hai đều hoạt động tốt cho người dùng quản trị. Đối với người dùng không phải là quản trị viên, bạn phải thêm quyền, một trong số họ được đề xuất ở đây :
GRANT VIEW SERVER STATE TO [user];
GRANT VIEW ANY DEFINITION TO [user];
Nếu bạn đặt hành động thất bại thành Thoát báo cáo thành công trong bước đầu tiên này, bạn sẽ không nhận được nhật ký công việc đầy dấu hiệu chữ thập đỏ xấu xí, thay vào đó, công việc chính họ sẽ chuyển thành dấu hiệu cảnh báo màu vàng.
Từ kinh nghiệm của chúng tôi, điều này không lý tưởng. Lúc đầu, chúng tôi đã áp dụng phương pháp này, nhưng nhanh chóng mất dấu vết về việc tìm kiếm các công việc thực sự có vấn đề, bởi vì tất cả các công việc sao chép thứ cấp làm lộn xộn nhật ký công việc với các thông điệp cảnh báo.
Những gì chúng tôi sau đó đã đi là:
Công việc proxy
Nếu bạn áp dụng khái niệm này, bạn thực sự sẽ cần tạo hai công việc cho mỗi nhiệm vụ bạn muốn thực hiện. Cái đầu tiên là "công việc proxy" kiểm tra xem nó có được thực thi trên bản sao chính không. Nếu vậy, nó bắt đầu "công việc công nhân", nếu không, nó chỉ kết thúc một cách duyên dáng mà không làm lộn xộn nhật ký với các thông báo cảnh báo hoặc lỗi.
Mặc dù cá nhân tôi không thích ý tưởng có hai công việc cho mỗi nhiệm vụ trên mỗi máy chủ, tôi nghĩ rằng nó chắc chắn sẽ dễ bảo trì hơn và bạn không phải đặt hành động thất bại của bước để Thoát khỏi thành công báo cáo công việc , đó là một chút lúng túng.
Đối với các công việc, chúng tôi áp dụng một kế hoạch đặt tên. Công việc proxy chỉ được gọi {put jobname here}
. Công việc công nhân được gọi {put jobname here} worker
. Điều này cho phép tự động hóa bắt đầu công việc worker từ proxy. Để làm như vậy, tôi đã thêm thủ tục sau vào cả hai dbs chính:
CREATE procedure [dbo].[procStartWorkerJob](@jobId uniqueidentifier, @availabilityGroup sysname, @postfix sysname = ' worker') as
declare @name sysname
if dbo.svf_AgReplicaState(@availabilityGroup)=0
print 'This is not the primary replica.'
else begin
SELECT @name = name FROM msdb.dbo.sysjobs where job_id = @jobId
set @name = @name + @postfix
if exists(select name from msdb.dbo.sysjobs where name = @name)
exec msdb.dbo.sp_start_job @name
else begin
set @name = 'Job '''+@name+''' not found.'
raiserror (@name ,2,1)
end
end
GO
Điều này sử dụng svf_AgReplicaState
chức năng hiển thị ở trên, bạn có thể dễ dàng thay đổi điều đó để kiểm tra bằng cách sử dụng tên cơ sở dữ liệu thay vì gọi hàm khác.
Từ bước duy nhất của công việc proxy, bạn gọi nó như thế này:
exec procStartWorkerJob $(ESCAPE_NONE(JOBID)), '{my_group_name}'
Điều này sử dụng các Token như được hiển thị ở đây và ở đây để lấy id của công việc hiện tại. Quy trình sau đó lấy tên công việc hiện tại từ msdb, nối worker
vào nó và bắt đầu công việc worker bằng cách sử dụng sp_start_job
.
Mặc dù điều này vẫn không lý tưởng, nhưng nó giữ cho nhật ký công việc gọn gàng và dễ bảo trì hơn so với tùy chọn trước đó. Ngoài ra, bạn luôn có thể chạy công việc proxy với người dùng sysadmin, vì vậy việc thêm bất kỳ quyền bổ sung nào là không cần thiết.