Hentikan pekerjaan jika tidak dilakukan pada replika utama
Untuk kasus ini, setiap pekerjaan di kedua server membutuhkan salah satu dari dua cuplikan kode berikut sebagai Langkah 1:
Periksa dengan nama grup:
IF master.dbo.svf_AgReplicaState('my_group_name')=0
raiserror ('This is not the primary replica.',2,1)
Periksa dengan nama basis data:
IF master.dbo.svf_AgReplicaState('my_db_name')=0
raiserror ('This is not the primary replica.',2,1)
Jika Anda menggunakan yang kedua ini, waspadalah terhadap basis data sistem - menurut definisi mereka tidak dapat menjadi bagian dari grup ketersediaan apa pun, jadi itu akan selalu gagal bagi mereka.
Keduanya berfungsi di luar kotak untuk pengguna admin. Untuk pengguna non-admin, Anda harus menambahkan izin tambahan, salah satunya disarankan di sini :
GRANT VIEW SERVER STATE TO [user];
GRANT VIEW ANY DEFINITION TO [user];
Jika Anda menetapkan tindakan kegagalan untuk Berhenti sukses melaporkan pekerjaan pada langkah pertama ini, Anda tidak akan mendapatkan log pekerjaan penuh dengan tanda silang merah jelek, untuk pekerjaan utama mereka akan berubah menjadi tanda peringatan kuning.
Dari pengalaman kami, ini tidak ideal. Kami awalnya mengadopsi pendekatan ini, tetapi dengan cepat kehilangan jejak mengenai menemukan pekerjaan yang sebenarnya memiliki masalah, karena semua pekerjaan replika sekunder mengacaukan catatan pekerjaan dengan pesan peringatan.
Apa yang kemudian kami lakukan adalah:
Pekerjaan proxy
Jika Anda mengadopsi konsep ini, Anda sebenarnya harus membuat dua pekerjaan per tugas yang ingin Anda lakukan. Yang pertama adalah "pekerjaan proxy" yang memeriksa apakah itu dieksekusi pada replika utama. Jika demikian, ia memulai "pekerjaan pekerja", jika tidak, itu hanya berakhir dengan anggun tanpa mengacaukan log dengan pesan peringatan atau kesalahan.
Meskipun saya pribadi tidak suka gagasan memiliki dua pekerjaan per tugas di setiap server, saya pikir itu pasti lebih dapat dipertahankan, dan Anda tidak perlu mengatur tindakan kegagalan dari langkah untuk Keluar dari kesuksesan pelaporan pekerjaan , yang sedikit canggung.
Untuk pekerjaan, kami mengadopsi skema penamaan. Pekerjaan proxy baru saja dipanggil {put jobname here}
. Pekerjaan pekerja disebut {put jobname here} worker
. Ini memungkinkan untuk secara otomatis memulai pekerjaan pekerja dari proksi. Untuk melakukannya, saya menambahkan prosedur berikut ke kedua master dbs:
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
Ini menggunakan svf_AgReplicaState
fungsi yang ditunjukkan di atas, Anda dapat dengan mudah mengubahnya untuk memeriksa menggunakan nama database sebagai gantinya dengan memanggil fungsi lainnya.
Dari dalam satu-satunya langkah pekerjaan proxy, Anda menyebutnya seperti ini:
exec procStartWorkerJob $(ESCAPE_NONE(JOBID)), '{my_group_name}'
Ini menggunakan Token seperti yang ditunjukkan di sini dan di sini untuk mendapatkan id pekerjaan saat ini. Prosedur kemudian mendapatkan nama pekerjaan saat ini dari msdb, menambahkannya worker
dan memulai pekerjaan pekerja menggunakan sp_start_job
.
Meskipun ini masih tidak ideal, itu membuat log pekerjaan lebih rapi dan dapat dipelihara daripada opsi sebelumnya. Selain itu, Anda selalu dapat menjalankan pekerjaan proxy dengan pengguna sysadmin, jadi menambahkan izin tambahan tidak diperlukan.