Yıllardan beri SQL Server’ ın ihtiyaçların hepsini tam olarak karşılayamayan FailOver seçenekleriyle boğuşmuş ve bir türlü aradığı o mükemmel çözümü bulamamış bir DBA olarak nihayet AlwaysOn ile tanıştınız. Bu teknolojide Log Shipping, Replication, Mirroring, SQL Clustering teknolojilerinin tüm eksiklerinin giderildiğini ve müthiş bir ürün olduğunu gördünüz. Hemen bin bir hevesle testlerinizi tamamladınız ve yapınızı AlwaysOn’ a geçirdiniz.
Gerçekten söylendiği gibi gayet başarılı bir şekilde çalışan, raporlama ile ilgili yükünüzü dağıtan hatta Disaster Site ile senkronizasyonunuzu sağlayan bu sistemde sıra Otomatik FailOver seçeneğini enable yapmaya gelmiştir. Fakat bu noktada bir eksiklik ortaya çıktı! Job ve Loginlerin entegre edilmemesinden dolayı FailOver’ ı otomatik olarak yapamayacağınızı keşfettiniz ve bu sorunun önüne geçmek için internette araştırmaya koyuldunuz. Bu konuda yapılmış bir tane araç var manuel olarak belirli zamanlarda aktarım yapıyor fakat sql loginlerin sid bilgilerini taşıyamamaktadır. Pek sonuç alamayacaksınız maalesef. En azından bu işi otomatik yapan bir ürün yok.
Bizler, LC Waikiki DBA ekibi olarak bu noktada her şeyi Microsoft’ tan beklememek lazım diyerek Login ve Jobların otomasyonunu da kendimiz halledelim dedik. Çünkü OLTP sunucumuz üzerinde çok sık değişikliğe uğrayan 2.500 ün üstünde Login ve 260 tan fazla Job bulunuyor. Biz bu yapıyı şuan aktif olarak kullanmaktayız ve bu sorunumuz çözüldü. Bu makalede bu otomasyonun nasıl hazırlanacağını inceleyeceğiz.
Öncelikle AlwaysOn sunucularının dışında bir Otomasyon sunucusuna ihtiyacımız var. Bu sunucu üzerinde ListenerName ve her node için Linked Server oluşturmamız gerekiyor. (Tabi ikinci faz olarak bu yapıyı SSIS e çevirmeyi düşünüyoruz ama hızlıca aksiyon alabilmek için bu şekilde bir yol izledik. ) Otomasyon sunucusunun kullandığı LinkServer userlar’ ı hiç uğraşmadan direk sysadmin yapın J Bu yüzden otomasyon sunucunuz üzerinde başka bir şey bulunmaz ise daha iyi olacaktır.
Tüm süreçlerde Microsoft’ un hazır sp lerinden faydalanacağız. Çünkü Support düşsün istemiyoruz.
Süreci aşağıdaki aşamalara bölebiliriz:
Loginlerin Aktarılması:
- Primary Node üzerinde silinmiş olan Loginlerin Secondary Node’ lar üzerinden silinmesi,
- Primary Node üzerinde değiştirilmiş ya da yeni eklenmiş Loginlerin Secondary Node lar üzerinde oluşturulması,
- Job Kategorilerinin Aktarılması:
- Primary Node üzerinde silinmiş olan Job kategorilerinin Secondary Node’ lar üzerinden silinmesi, (Bu işlem Joblar entegre edildikten sonra yapılmalıdır)
- Primary Node üzerinde değiştirilmiş ya da yeni eklenmiş job kategorilerinin Secondary Node lar üzerinde oluşturulması, (Bu işlem Joblar entegre edildilmeden önce yapılmalıdır)
Jobların Aktarılması:
- Primary Node üzerinde silinmiş olan job Secondary Node’ lar üzerinden silinmesi,
- Primary Node üzerinde değiştirilmiş ya da yeni eklenmiş job Secondary Node lar üzerinde oluşturulması,
Tamamlanacak yapı sadece Listener bilgisi alarak tüm işlemleri kendisi yapacak şekilde tasarlanmalıdır. Öncelikle Listener name den Primary sunucu ve Secondary sunucuların Hostname lerini alacak iki adet Sp hazırlıyoruz. Sp hazırladık çünkü bu sorguların dinamik sql olması gerekiyor. Sorgular aşağıdaki gibi olacaktır:
Primary Sunucu İçin:
Select distinct replica_server_name from @Listener.Master.sys.dm_hadr_availability_replica_cluster_states arcs
Join @Listener.Master.sys.dm_hadr_availability_replica_states ars on arcs.replica_id=ars.replica_id where role_desc=’PRIMARY’
Secondary Sunucular İçin:
Select distinct replica_server_name from @Listener.Master.sys.dm_hadr_availability_replica_cluster_states arcs
Join @Listener.Master.sys.dm_hadr_availability_replica_states ars on arcs.replica_id=ars.replica_id where role_desc=’SECONDARY’ and operational_state is NULL
Sonrasında üç adet tabloya ihtiyacımız var:
Bunların ilki başarılı Senkron tarihlerini her sunucu için kaydedecek. Bu tabloda basit bir şekilde objenin ne olduğu, tarih, sunucu adı ve mesaj kolonları bulunması yeterlidir. Burada dikkat edilmesi gereken konu Secondary sunucularda senkron başarılı olduğunda Primary sunucu için de bir kayıt girilmesi gerektiğidir. Aksi halde FailOver yaptığımızda tüm objeleri baştan entegre ederiz.
İkinci tablomuz her Secondary sunucu için oluşturulması gereken Login ve Job scriptlerini barındıracak olan entegrasyon tablosudur. Bu tablo, her Secondary sunucu için değiştirilmiş ya da yeni oluşturulmuş objelerin adını ve create scriptlerini barındıran, her obje için oluşturma işleminin tamamlanıp tamamlanmadığı bilgisini içeren tablo olacaktır.
Üçüncü ve son tablomuz ise hata kontrolü için try catch bloklarımızdan gelen hata mesajlarının yazılacağı tablodur.
Login’ lerin Aktarılması:
Loginlerin entegrasyonu ile aynı yolu izliyoruz. Öncelikle birincil sunucudan silinmiş olan Jobları ikincil sunuculardan temizliyoruz. Ardından birincil sunucuda son entegrasyon tarihinden sonra değişen ve yeni eklenen Jobları her ikincil sunucu için tespit ederek entegrasyon tablomuza yazıyoruz. Burada dikkat edilmesi gereken önemli bir nokta tarih tespiti yaparken karşımıza çıkmaktadır. Çünkü Joblar için modified date tek başına yeterli değildir. Jobların Schedule değişikliklerini buradan yakalayamazsınız. Bunu yakalamak için sysschedules tablosundan da faydalanmanız gereklidir. Bu iki tabloda son entegrasyon tarihinden yeni olan joblarımızı tespit ederek entegrasyon tablomuza yazıyoruz.
Oluşan listede ki Jobların ikincil sunucular üzerinde oluşabilecek şekilde create scriptlerini hazırlayarak entegrasyon tablomuzu güncelliyoruz.
Set @String=’
Insert Into ##SenkronJobList (Name,HedefSunucu)
Select Name, (Select ”’+@SEC+”’) From
(
/*Modify date bilgisi sayesinde yeni eklenen ve değişen jobları yakalıyoruz*/
Select Name from ‘+@PRI+’.Msdb.dbo.sysjobs Where date_modified >
(Select AlwaysOnSync.Fn_GetLastSyncDate (”’+@Obje+”’,”’+@SEC+”’))
and Name <>”syspolicy_purge_history”
and Name not like ”/*Excluded Jobs*/’’
/*Schedule değişikliklerini yakalıyoruz*/
Union
Select j.name from ‘+@PRI+’.Msdb.dbo.sysjobs j
Join ‘+@PRI+’.Msdb.dbo.sysjobschedules jsc on j.job_id=jsc.job_id
Join ‘+@PRI+’.Msdb.dbo.sysschedules sc on jsc.schedule_id=sc.schedule_id
Where sc.date_modified > (Select AlwaysOnSync.Fn_GetLastSyncDate (”’+@Obje+”’,”’+@SEC+”’))
and j.Name <>”syspolicy_purge_history”
and j.Name not like”IndexIslem%”
) Liste’
Exec Sp_ExecuteSql @String
Yukarıda ki gibi bir dynamic Sql script le senkron edilecek Jobları yakalıyoruz.
Bu konunun detayına girecek olursak alt tarafta çalışacak birkaç tane sp ye ihtiyacımız bulunuyor. Bunlar: belirtilen job a ait stepler için create scripti oluşturan, belirtilen job a ait Schedule lar için create scripti oluşturan ve belirtilen job a ait omurga scripti oluşturan prosedürlerdir. Bunları çatıda her job için gerekli sayıda çalıştıracak ayrı bir prosedürün içinde topluyoruz ve bu prosedürü de her job için çalışarak tablomuza create scriptleri basacak şekilde organize ediyoruz. Burada dikkat edilmesi gereken konu ikincil sunucularda job oluştuğunda job id leri değişecek olmasıdır. Dolayısıyla çalışmalarımızda birincil sunucudan job id ile aldığımız verileri ikincil sunuculara iletirken job name ile iletiyor olmamız gerekmektedir. Msdb içinde zaten job,step ve Schedule oluşturmak için hazır prosedürler vardır. Bunları kullanarak dinamik sorgular ile gerekli alanları birincil sunuculardan getirmemiz gerekiyor.
Entegrasyon tablomuzda oluşturulmaya hazır hale gelen joblarımızı öncelikle her ikincil sunucu üzerinden var ise silip ardından Scriptlerimizle tekrardan oluşturuyoruz.
İşlemler başarılı bir şekilde tamamlandığında her sunucumuz için senkron tablomuza tarih ekliyoruz.
Bu makalemizde LC WAIKIKI olarak In-House geliştirdiğimiz AlwaysOn otomasyonunun detaylarını sizlerle paylaştık. Şuanda aktif bir şekilde bu mekanizma çalışmakta ve hayatımızı kolaylaştırmaktadır.
Bu konuda sorun yaşayan arkadaşlara destek olmaktan mutluluk duyarız.