5 Aralık 2017 Salı

Kim korkar kritik bir ayarı değiştirmekten? (İpucu: temkinli olmakta fayda var)

Birkaç ay önce sahadaki sağlık kontrolü çalışmalarım sırasında karşılaştığım sorunlardan birini bu yazı ile anlatmıştım. Bu duruma benzer bir sorunun geçenlerde başka bir ortamda yaşandığına şahit oldum.

Sorun oluştuğunda SQL Server Management Studio ve uygulamalar ile SQL Server Instance'ına bağlanmaya çalıştığımızda şöyle hatalar oluşuyordu:

"A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 0 - The specified network name is no longer available.) (Microsoft SQL Server, Error: 64)"

Açıkçası özellikle aşina olmayanlar için oldukça kafa karıştırıcı bir mesaj. Hata mesajını özetle ve mealen şöyle Türkçeye çevirebiliriz "Sunucuya bağlantı sağlandı, ama sonra bir hata oluştu (Belirtilen ağ adı artık ulaşılabilir değil)". Yani sunucuya ulaşabiliyoruz, ama sonra bir hata oluşuyor ve birden sunucu ulaşılamaz oluyor. 

Not: SQL Server'da buna çok benzer, fakat farklı ibareler içeren çeşitli hata mesajlarıyla karşılaşılabilir. Birebir aynı olmadığı sürece sorunları birbirine karıştırmamakta fayda var. SQL Server bağlantı sorunlarıyla ilgili daha fazla bilgi için referans yazımı bu adresten inceleyebilirsiniz. Ayrıca Aaron Bertrand'tan 18456 hatalarıyla ilgili güzel bir referans yazısını da bu adreste bulabilirsiniz.

Sorun anında yeni oturum açmak pek mümkün olmadığı için varolan açık oturumları kullandık ve hata kayıtlarını kontrol ettiğimizde şu hataları gördük:

"Could not connect because the maximum number of user connections has already been reached."

SQL Server'da normal şartlar altında, yani varsayılan olarak "User Connection" ayarı sınırsızdır, daha doğrusu 0'dır ve bu da 32.767'ye karşılık gelir. 

Not: Tabii ki 32.767 nihayetinde bir sınırdır, ama pratikte bu sınıra ulaşmanız pek kolay değil.

Not: Benzer sıkıntılı durumlarda Dedicated Administrator Connection (DAC) hayat kurtarır. Her SQL Server veritabanı yöneticisi muhakkak bu kavramı ve ne zaman, nasıl kullanılabileceğini bilmelidir.

Sanırım şimdiye kadar birçoğunuz durumu anlamıştır. "User Connection" ayarı çok daha küçük bir sayı ile değiştirilmiş. Her ortamda "lütfen bilmediğiniz, emin olmadığınız, yeterince test etmediğiniz ayarı değiştirmeyin" diye bas bas bağırıyoruz; ama "tarih tekerrürden ibarettir" sözü, anlamı gibi kendini de tekrar ettirip duruyor.

Sonradan öğrendiğime göre bu değişikliğe neden olan motivasyon, sunucunun zaten X sayısından fazla kullanıcı bağlantısını kaldıramayacağı düşüncesiymiş. Fakat bu senaryoda yanılınan temel nokta şu oldu bence, bağlantılar aktif olsun, pasif olsun, bu ayar her türlü bağlantıyı kapsar. Örneğin sorun esnasında kontrol ettiğimde varolan bağlantıların %80'i pasifti (sleeping) ve ancak %20'si aktif, çalışan bağlantıydı. Bu normal mi, anormal mi ayrı bir tartışma konusu; ama bu kullanıcı bağlantı sayısı kesinlikle sunucunun kaldırabileceğinin çok altındaydı. Yani eğer bu ayar bu şekilde suni olarak değiştirilmeseydi, bu durumdan kaynaklanan bir kesinti olmayacaktı. Sonuç itibariyle elbette her sunucu kaynağının ve sistemin kaldırabileceği bir yük var, ama buna suni olarak ve yeterince ince eleyip sık dokumadan müdahale etmeye ne gerek var?

Not: Özellikle kompleks sistemlerde türlü anormallikler, beklenmedik durumlar muhakkak, olacaktır (dikkat "olabilir" demiyorum); sunucularımızın ayarları ve donanım kaynakları özellikle kritik ortamlarda bu tür anormallikleri ve anormal yükleri kaldırabilecek şekilde düşünülmeli ve tasarlanmalıdır. 

Sistemin sağlığını etkileyebilecek benzer değişiklikler yapılmadan önce bu değişikliklerin olası sonuçları, özellikle çok kritik canlı sistemlerde muhakkak etraflıca düşünülmelidir. Ayarlar, kavramlar ve özellikler hakkında resmi dokümantasyon ve ilgili değişikliği uygulamış insanların gerçek hayat tecrübeleri muhakkak dikkate alınmalı, incelenmeli, okunmalı ve dinlenmelidir. Ayrıca böyle değişiklikleri canlı ortamınızda uygulamadan önce kendi ortamınız için testler ve gözlemler yapmanızda büyük fayda var. Değişiklik öncesinde (yeterli bir süre boyunca) ne durumda olduğunuzu, değişiklik sonrasında hangi duruma geldiğinizi, metriklerin nasıl ve ne yönde değiştiğini mutlaka bilmelisiniz. Bunları bilmezseniz, yönetemezsiniz. Yönetemediğinizde de durum kontrolden çıkar.

Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com

27 Kasım 2017 Pazartesi

Hata: Servis hesabının Always On Availability Groups kurulumuna etkisi

Geçen gün bir müşterimde Always On Availability Groups kurulumu yaparken önceden karşılaşmadığım bir sorun ile karşılaştım. Müsait olunca konu hakkında bir blog yazısı yazarım diye o anda ekran görüntüsünü almıştım. Soruna dair ilgili ekran görüntüsünü aşağıda paylaşıyorum.

Kurulum yaparken karşılaştığım sorun

Bilgi mesajı şöyle diyordu:
"The Endpoints tab lists at least one endpoint that uses only Windows Authentication. However, the server instance might be running under a nondomain account. To use the listed endpoint, change the corresponding SQL Server service account to a domain account. To continue using the nondomain account, after the endpoint to use a certificate."

SQL Server bir nedenden dolayı Replica'lardan birinin Domain hesabıyla çalışmadığını düşünüyordu. Fakat "SQL Server Service Account" sütununda da görülebileceği üzere iki hesap da Domain hesabı. Kuruluma bu şekilde devam ettiğimde kurulum bir türlü tamamlanmıyordu. Bir hata da vermiyordu veya verinceye kadar bekleyememiştim, ama bir yerlerde sıkıntı olduğu artık çok netti.

Kurulumu sadece arayüzle değil, T-SQL ile denediğimde de aynı sonuç ile karşılaşıyordum. Yukarıdaki bilgi mesajı gelmiyordu, ama kurulum da tamamlanmıyordu.

Endpoint'leri de kontrol etmiştim, herhangi bir anormallik yoktu.

Yukarıdaki ekran görüntüsündeki gibi farklılıkları oldum olası hiç sevmem. Yani örneğin Replica'lardan birinin servis hesabı "servis_hesap_adi@domain_adi" biçimindeyken diğerininkinin "domain_adi\servis_hesap_adi" olması benim için rahatsız edici bir durum. O anda tabii ki sorunun nedeninin bu olduğundan %100 emin olmasam da, %90'lık çok güçlü bir tahminle sorunun bu olacağını düşünmüştüm. 

Sonra test etmek için bir SQL Server kurulu sunucuda SQL Server Configuration Manager kullanarak 2. Replikanın servis hesabınının biçimini de canlı sunucudaki gibi "servis_hesap_adi@domain_adi" olarak değiştirmek istedim ve bunun yapılamadığını gördüm. Yani istesem de SQL Server Configuration Manager ile bir servis hesabını bu yazım biçimiyle atayamıyordum. O anda anladım ki birisi bu hesap değişikliğini SQL Server Configuration Manager yerine Services.msc ile yapmıştı, ki bu hiç iyi bir pratik değildir. Tüm SQL Server servis hesabı değişikliği işlemlerini SQL Server Configuration Manager aracıyla yapmalısınız. Çünkü bu sırada sadece servis hesabı değiştirilmez, aynı zamanda bu hesaba arkaplanda gerekli bazı yetkiler ve rol üyelikleri uygulanır. Eğer bu işi Services.msc ile yaparsanız sadece servis hesabı değişmiş olur. Ayrıca bu örnekte de görülebileceği üzere SQL Server servis hesabı değişikliğini "domain_adi\servis_hesap_adi" yerine "servis_hesap_adi@domain_adi" biçimiyle yapmış olabilirsiniz, ki bu örnekten de görülebileceği gibi bu biçimi kullanmak ilginç sorunlara neden olabiliyor.

Not: Bu noktada bir belirsizliğe dikkat çekmek istiyorum. Bu yazıya konu olan sorun SQL Server servis hesabının SQL Server Configuration Manager yerine Services.msc'den değiştirilmesinden de kaynaklanıyor olabilir, servis hesabının "domain_adi\servis_hesap_adi" biçimi yerine "servis_hesap_adi@domain_adi" biçimiyle belirlenmiş olmasından da kaynaklanıyor olabilir. Örneğin SQL Server servis hesabını Services.msc'den değiştirip, bu işlemi yaparken de "domain_adi\servis_hesap_adi" biçimini kullansaydım da sorun çözülebilirdi belki? Bu, ayrı bir test gerektiriyor. Ortam canlı olduğu için o anda bunun testini yapamadım. Eğer başka bir ortamda bunu test edebilirsem bu yazıyı güncelleyeceğim.

Servis hesabı değişimi (normal şartlar altında) kısa da olsa kesinti gerektiren bir değişiklik. İlgili yöneticilerle planlı bir kesinti için anlaştık ve zamanı geldiğinde canlı sunucudaki SQL Server Database Engine servis hesabını SQL Server Configuration Manager kullanarak ve "domain_adi\servis_hesap_adi" biçiminde değiştirdim. Bu değişiklikten sonra Always On Availability Groups kurulumunu tekrar denedim ve yukarıda paylaştığım ekran görüntüsündeki hata ile karşılaşmadım.

Yukarıdaki bilgi mesajıyla karşılaşmadığım gibi kuruluma devam ettikten sonra da kurulumun başarıyla tamamlandığını gördüm. Yani bu değişiklikle sorunum çözüldü. Olur da bir gün başka bir arkadaşım karşılaşırsa diye paylaşmak istedim.

Ekrem Önsoy
Microsoft SQL Server Danışmanı


3 Kasım 2017 Cuma

Firmam 2. yaşını doldurdu, kutlu olsun!

Firmamı kuralı 2 sene oldu ve bu vesileyle bir teşekkür yazısı yazmak istedim.

2 sene önce sevgili dostum Yiğit Aktan'ın (t) da kışkırtmalarıyla artık kendi firmamı kurmam kaçınılmaz olmuştu. Ben de kaçınmadım, üşenmedim ve uzun yıllardır aşkla kullandığım, inciğine, cıncığına kadar kurcaladığım, hakkında sabah akşam okuyup dersler aldığım, sınavlarına girip, ödül kazandığım Microsoft SQL Server ürünü konusunda profesyonel danışmanlık hizmeti vermeyi hedeflediğim firmamı kurdum.


www.ekremonsoy.com adresindeki ilk yazım

Firmamı kurduğumdan beri sağolsun sevgili eşim başta olmak üzere, dostlar ve piyasanın çeşitli uç ve bucağına dağılmış olan eski iş arkadaşlarım desteklerini hiç esirgemediler. Bu süreçte bazılarıyla yollarımız farklı firmalarda tekrar kesişti, bazılarıyla tekrar birlikte çalışma fırsatımız oldu.

Bu 2 yıllık süreçte İzmir'deki bir matbaadan, Bursa'daki bir girişimciden, dünya çapında binlerce insan çalıştıran şirketlere kadar birçok şirket ile çalışma fırsatım oldu. Aşağıda, hala birçoğuyla çalıştığımız bu şirketlerin bazılarının isimlerini (alfabetik) paylaşmaktan memnuniyet duyuyor ve bana güvenip, benimle çalıştıkları için teşekkür ediyorum.

- Ada Yazılım
- Alp Havacılık
- Borusan Lojistik
- Doğa Sigorta
- Edenred Türkiye
- Ericsson
- Morhipo.com
- Papara
- Penta
- Pronet
- RND
- Tiposoft

Her geçen gün öğrendiğim yeni şeyleri 20 yılın tecrübesiyle ve ilk günkü hevesle uygulayıp, paylaşma fırsatı bulduğum için ve yetmezmiş gibi bir de bu sayede faturalarımı ödeyebildiğim için çok müteşekkirim, hayata ve katkısı olan herkese.

Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com

29 Eylül 2017 Cuma

Veritabanınızdaki veriler ne kadar güvende sizce?

Güvenlik gündemden düşmeyen ve düşmeyecek bir konu, sonuçta İhtiyaçlar Hiyerarşisinin de 2. basamağında. Hatta malumunuz son günlerde her yerde Gartner'ın Güvenlik Danışmanlığı dalında ve ciro bakımından 5 yıl art arda 1. sıraya koyduğu Deloitte'ta yaşanan güvenlik açığı konuşuluyor. Peki sizin sistemlerinizin güvenliği ne alemde? Bunu yeterince sorguluyor musunuz?

Bu yazımda size son günlerde yaşadığım bir güvenlik sorunundan ve bir Microsoft SQL Server veritabanı yöneticisinin gözünden güvenlik ile ilgili alınması gereken tedbirlerden bahsedeceğim.

Kısa bir süre önce yönetimini yaptığım sunucuların birinden güvenlik alarmları geldiğini gördüm, durumu analiz edip hemen ilgili IT yöneticisine bildirdim. O da ilgili diğer arkadaşlara bildirdi ve sisteme bir saldırı olduğu netleşti. İlgili ekip tarafından gerekli önlemler alındı ve atak engellenmiş oldu. 

Peki saldırının türü neydi ve saldırıyı nasıl fark ettim? Microsoft SQL Server ürününün varsayılan olarak böyle bir alarmı veya mekanizması yok. Fakat bunun temel altyapısı var. Eğer biraz tecrübeniz varsa, biraz bu konulara kafa yoruyorsanız ve üşengeç biri de değilseniz o zaman eminim sizin de aklınıza gelmiştir bu mekanizma ve bazılarınız zaten uygulamıştır. 

Bakım ve destek anlaşması kapsamında ilgili sunuculara kurduğum izleme sistemindeki onlarca kontrolden biri şöyle:
- Her X dakikada bir Error Log dosyası içerisindeki (ki Error Log dosyasına yazılan her şey Windows Application Event Log'a da yazılır, yani alternatif bir yöntem) tüm "Login Failed" kelimeleri geçen hatalar taranır, 
- Eğer bulunan kayıt sayısı beklenilen/normal sayılan değerden yüksekse, ilgili yöneticilere e-posta ile (aşağıdaki resimdeki gibi bir liste) bildirilir.

Çok basit bir oto-denetim, ama çok etkili. Bahsettiğim saldırıyı güvenlik, ağ ve sistem yönetiminden önce benim fark etmemi sağlayan yöntem bu idi.

Bu saldırıya "Brute Force" mu desek, DDoS mu? Sonuç itibariyle farklı farklı IP adreslerinden, farklı farklı kullanıcı adı ve şifre kombinasyonuyla veritabanına girilmeye çalışıldı.


Saldırı sırasında oluşan hatalar

Çok iyi hatırlıyorum, 2 sene önce bir başka ortamda da aynen yukarıdaki hata mesajlarına benzer hatalar oluşmuştu. Müşteriyle daha yeni bakım ve destek anlaşması yapmıştık. Bana sunucularının çok kritik olduğundan bahsetmişti. Sunucuya daha ilk bağlandığımda hata kayıt dosyalarının böyle mesajlarla dolu olduğunu görmüştüm. Kim bilir ne süredir saldırı altındaydı ve bundan hiç haberi yoktu. Bunu müşteriyle ilettiğimde tüyleri diken diken olmuştu.

Microsoft SQL Server, yıllardır güvenlik açıkları kapsamında rakiplerine göre katbekat güvenli bir ilişkisel veritabanı ürünüdür. Bununla birlikte, nasıl güvenli olduğundan emin olduğunuz herhangi bir aracı, gereci kullanırken tüm güvenlik önlemlerini almanız gerekiyorsa, SQL Server'ı da kullanırken en azından temel güvenlik önlemlerini almalısınız.


Kaynak: Microsoft'un bir sunumundan...

Uzun yıllardır gerek projeler kapsamında, gerekse tam zamanlı olarak verilerin çok hassas olduğu sağlık ve finans sektörlerlerinden birçok kurumda çalışmalar yaptım. Kontrolümde olan sunucular yüzlerce kez dahili ve harici denetimlere tabi tutuldu. Aşağıda sizlerle bu tecrübelerimden aklıma gelen başlıca maddeleri paylaşmak istiyorum. Eğer birçoğu klasikleşmiş bu maddeleri ortamınıza uygulayabilirseniz, SQL Server kapsamında alınabilecek başlıca güvenlik tedbirlerini almış olursunuz. Hem kendi güvenliğinizi sağlamış olursunuz, hem de olası denetimlerde başınız ağrımaz.

- SQL Server'ın varsayılan (daha fazla bilgi için) portu 1433'tür, bunu dünyadaki tüm saldırganlar bilir. Farklı bir port kullanın.

- SQL Server kurulumuyla birlikte "sa" hesabı varsayılan olarak gelir. Bunu da aynı şekilde tüm saldırganlar bilir. Bu nedenle yukarıdaki loglarda da görebileceğiniz üzere "sa" hesabı da saldırılan hesaplardan biriydi. "sa" hesabının yerine başka kullanabileceğiniz "sysadmin" rolü üyesi hesaplar olduğundan emin olduktan sonra "sa" hesabını "Disable" duruma getirin veya "sa" hesabının adını değiştirin.

- Guest hesabını kullanmayın. Public kullanıcısına yetki vermeyin.

- Kullanıcılarınızın Login'ler için basit veya boş şifreler belirleyebilmesini engelleyin. 

- Mümkün olduğunca SQL Authentication yerine Windows Authentication'ı tercih edin.

- Yazılımcılarınız "SQL Injection" konusunda bilinçlendirilmeli. Uygulama arayüzlerinde kullanılan metin kutuları sadece almaları gerektiği türden ve uzunlukta değerler almalı. Örneğin sayısal bir değer kutusuna metin girilememeli veya TC Kimlik No alanına 11'den fazla karakter girilememeli.

- Uygulamalarınız sadece ihtiyacı olan uygulama kullanıcılarıyla erişsin veritabanına. Böylece uygulamanızdaki bir açık vasıtasıyla veritabanına ulaşılırsa, sadece uygulamanın ulaşabileceği veriye ulaşılabilir olsun, daha fazlası yapılamasın.

- Kod yazarken güvenlik (ve performans) açısından mümkün olduğunca dinamik SQL kullanmayın. Kullanacağınız zaman da dinamik SQL metinlerini güvenlik denetimine tabi tutmadan çalıştırmayın.  Örneğin "Doğum Yılı" veya benzer bir veri giriş kutusuna kesme işareti, "DROP, ALTER, GRANT, EXECUTE" gibi komutlar girilememeli.

- Uygulama yazarken kesinlikle ve hiçbir zaman son kullanıcının gireceği veriye güvenmeyin. Sadece güvenlik açısından değil, performans ve işlevsellik açısından da.

- Uygulama yazılırken sadece işlev değil, güvenlik (ve performans) odaklı yazılmalı. Yazılımcılar bu konuda net olarak bilinçli ve eğitimli olmalı. Projeler sadece işlevsellik ihtiyaçlarının giderileceği kadar sürelendirilmemeli. Yazılımcılar ve iş analistleri üstünde zaman baskısı olursa herkes sadece işlevselliğe odaklanır. Güvenlik ve performans testleri için de projelere süreler eklenmeli. Gerçekçi süreler! Zaman baskısı nedeniyle birçok şirkette hala doğru düzgün işlevsellik testi bile yapılmadan canlıya kod taşıması yapıldığını biliyorum maalesef.

- Her seviyedeki tüm kullanıcılara, sadece gerektiği kadar yetki verilmeli. Birçok ortamda gördüğümüz gibi tüm kullanıcılar "sysadmin" olmasın veya tek bir kullanıcıyla (genellikle "sa") tüm sistemi yönetmeye kalkmayın.

- Veritabanı yöneticisinin işlemleri dahil tüm kritik işlemleri 3. parti araçlarla veya SQL Server'ın sağladığı imkanlarla kayıt altına alın. Fakat birçok ortamda olduğu gibi sadece işlemleri kaydetmekle kalmayın, bu kayıtları otomatik olarak inceleyin ve anlam çıkartın ve sonuçlar için alarmlar ve raporlar ürettirin. 

- Görevler ayrılığı ilkesini işletin. Domain veya Windows yöneticileri için "sysadmin" rolüyle kullanıcılar olmadığından emin olun. Mümkünse herkes kendi işini yapsın. Örneğin bir önceki maddede bahsettiğim kayıt mekanizmasını hem kuran, hem yöneten aynı kişi olmamalı. Kayıt altına alınan işlemler değiştirilememeli.

- Sisteminizde her zaman neyin normal, neyin anormal olduğunu bilmelisiniz. Nasıl performans için bir referans hattınız varsa (var, değil mi?), güvenlik için de bir referans hattınız olmalı. Örneğin özellikle çok kritik tablolardan toplu sorgulamalar yapılmasını istemeyebilirsiniz ve böyle bir şey olduğunda haberdar olmak isteyebilirsiniz. Böyle tabloları belirleyin ve gerekli alarm mekanizmalarını kurun.

- Yazılımcılar, iş analistleri ve diğer personel uygulama kullanıcılarının şifrelerini bilmemeli. Bu bilgiler (Connection String) şifreli saklanmalıdır.

- Yazılımcılar, iş analistleri ve diğerlerinin doğrudan canlı sunuculara uygulama kullanıcılarının bilgileri ile bağlanamamasını sağlayın. Canlı sunuculara uygulama kullanıcıları kullanılarak ancak uygulama sunucularından veya ilgili sunuculardan ve uygulamalar aracılığıyla gelinebilmeli.

- Mümkünse canlı ortamınız için ağ bölümü ile koordineli çalışarak IP kısıtlaması koydurtun. Canlı ortamınıza mümkünse sadece belli IP adreslerinden/bloklarından (uygulama sunucuları) gelinebilsin.

- Gerek canlı ortamınız, gerekse geliştirme ve test ortamınızdaki hassas verilerinizi maskeleyin. Sadece yetkili kişiler, görmeleri gereken verilerin, görmeleri gereken kısımlarını görebilsinler. Hem bir veri sızıntısı durumunda ilgili, ilgisiz herkes zan altında kalmamış olur, hem saldırganların işi zorlaşmış olur, hem de olası sızıntının nereden kaynaklanabileceği hakkında inceleme yapacağınız daha dar bir alan olur.

- Veritabanı yedeklerinizi de canlı ortamınızı koruduğunuz gibi koruyun. Mümkünse yedeklerinizi şifreleyin (Backup Encryption SQL Server 2014 ile geldi). Yedeklere kimlerin erişebildiği net ve sınırlı olmalı. Ayrıca mümkünse kimlerin eriştiğinin kaydı tutulmalı ve raporlanmalı.

- SQL Server servis hesaplarınız olarak Local System gibi geniş yetkilere sahip hesapları kullanmayın. Eğer bir Domain hesabı kullanacaksanız bu normal bir "Domain User" hesabı olsun mesela.

- CLR veya xp_cmdshell gibi aktif olarak kullanılmayacak hiçbir özelliği etkinleştirmeyin. Kullanmayacağınız hiçbir SQL Server servisini veya uygulamayı veritabanı sunucunuza kurmayın.

- Daha ileri seviye güvenlik tedbirleri için örneğin diskteki veriyi ve yedekleri korumak için Transparent Data Encryption özelliğini kullanmayı düşünün. (İleri seviye. Enterprise Edition gerektirir.)

- Veriyi hareket halindeyken (uygulama ve veritabanı arasında gidip geliyorken) ve veri veritabanında dururken şifreli olsun istiyorsanız SQL Server 2016 ile birlikte gelen Always Encrypted özelliğini kullanmayı düşünün. (İleri seviye, her senaryo için uygulanabilir değil. Enterprise Edition gerektirir.)

- Kullandığınız SQL Server versiyonunun güncel sürümlerini kullandığınızdan emin olun.

- Güvenlik haberlerini yakından takip edin, sadece yazılımlarınızı değil, kendinizi de güncel tutun.

Unutmayın, güvenlik sadece ağ katmanı veya daha çok bütçeniz varsa güvenlik bölümlerinde kullanılan pahalı araç gereçlerle sınırlı değildir. Diğer katmanlardan bağımsız olarak sadece veritabanında alacağınız önlemler de yeterli değildir. Geliştirdiğiniz ve kullandığınız uygulamalarınız da kesinlikle bir istisna değildir, olamaz. Güvenlik baştan sona bir bütündür, şirket sekreterinden girişteki güvenliğe, finans müdüründen yazılım mimarına kadar bir takım işidir. Bu katmanlar zincirindeki en zayıf halkanız kadar güçlüdür güvenliğiniz.


Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com

18 Eylül 2017 Pazartesi

Performans: Kendi kendini sabote etmek

Vahşi yaşamdaki Sahadaki sunucularda sağlık kontrolü ve performans iyileştirmesi gibi çalışmalar yaparken, hangi akla hizmet hiç anlam veremediğim bazı ilginç ayarlar yapıldığını, sunucularda aylardır oluşan hataların izlenmediğini ve haliyle herhangi bir müdahalede de bulunulmadığını görüyorum. Ahh, sonra bir de "SQL Server kötü" demiyorlar mı!

Bu tür durumlar, ki piyasada gerçekten çok yaygın, son model spor aracınızı el freni kalkık şekilde kullanmaya benziyor. Donanım kaynaklarına ve lisanslara onca para harcanıyor, fakat bu yatırımlardan verimli bir şekilde faydalanılamıyor.

Geçenlerde 16 işlemci çekirdekli bir sunucuda çalışma yaparken zaman zaman aşağıdaki hataların alındığını gördüm:

"New queries assigned to process on Node 0 have not been picked up by a worker thread in the last 240 seconds. Blocking or long-running queries can contribute to this condition, and may degrade client response time. Use the "max worker threads" configuration option to increase number of allowable threads, or optimize current running queries. SQL Process Utilization: 5%. System Idle: 93%."

Ve bu hatalarla birlikte Dump alınıyordu.

Bu hata mesajı sorguların uzun sürdüğünün, olası bağlantı hatalarının ve CPU kaynaklarının verimli kullanılmadığının işaretidir.

Bekleme tiplerini kontrol ettiğimde "Threadpool" bekleme tipinin "CXPACKET"tan hemen sonra geldiğini görüyordum. Konumuz dahilinde değil, ama "CXPACKET" bekleme tipi paralelliğin kullanıldığı tüm ortamlarda olur ve kendi başına doğrudan bir sorun anlamına gelmez. Fakat ilk 10 bekleme tipi arasında "Threadpool"u görüyorsanız ve bu da ikinci sıradaysa "Worker Thread"lerle ilgili bir sorununuz var ve buna odaklanmanız gerekir demektir.


Threadpool bekleme tipi sorununun görseli

Peki nedir bu "Threadpool" ve "Worker Thread"?

Threadpool, çok miktarda istemci sunucuya bağlandığında performansın optimize edilmesini sağlar. Kullanıcıların yaptığı talepler için, yani çalıştırdıkları sorgular için bir Thread havuzu oluşturur. Threadpool'da kullanılabilecek Worker Thread sayısını SQL Server sunucu mimarisi ve işlemci çekirdek sayısına göre Database Engine servisinin başlangıcında yapar. Bu şartlara göre oluşturulacak Worker Thread sayısını Microsoft'un dokümantasyonundan inceleyebilirsiniz.

Eğer bu hesaplamaya müdahale etmeniz gerekirse, ki şahsen henüz bunu gerektirecek bir durumla hiç karşılaşmadım, o zaman "Max Worker Thread" ayarını değiştirmeniz gerekir. Bu ayar varsayılan olarak 0'dır ve çok istisnai durumlar haricinde de 0 olarak kalması gerekmektedir.

Herhangi bir SQL Server Instance'ındaki o anki "Max Worker Thread" sayısını görmek için aşağıdaki komutu çalıştırabilirsiniz:

SELECT [max_workers_count] FROM sys.dm_os_sys_info;

"Max Worker Thread" ayarınızı görmek için de aşağıdaki komutu kullanabilirsiniz:

SELECT [value], [value_in_use] FROM sys.configurations WHERE [name] = 'max worker threads';

Eğer "Max Worker Thread" ayarınız için [value] ve [value_in_use] alanlarının değerleri 0 ise ayarınız varsayılan değerdedir ve önceden de belirttiğim gibi birçok ortam için de doğru olan değer budur. Eğer bu alanlardan herhangi biri 0 değilse, birisi bu ayarı değiştirmiştir ve eğer bunu gerçekten işini bilen birisi yapmadıysa büyük ihtimalle bu hatalı bir hamledir. Eğer bu ayarı değiştirmeniz gerekirse, değişikliği uyguladıktan sonra Database Engine servisini yeniden başlatmanız gerekir, aksi takdirde değişiklik hemen devreye girmez.

Gelelim Worker Thread'in ne olduğuna. SQL Server'da her bir işlemci çekirdeği Scheduler'la temsil edilir. SQL Server Instance'ınızda kaç tane Scheduler olduğunu, bunların kaç tanesinin kullanılabilir (Visible) olduğunu sys.dm_os_schedulers isimli DMV'yi sorgulayarak görebilirsiniz. Örneğin bazı Scheduler'lar sistem tarafından kullanılır, bazıları ise lisanslama yüzünden (bakınız) pasif durumda olabilir. Worker Thread'ler, Scheduler'lar tarafından kendine atanmış olan Task'ları (örneğin bir sorgunun çalışması veya log in işlemi gibi) çalıştırırlar. Mesela havuzda yeterince kullanılabilir Worker Thread olmazsa bu nedenle "Login failed" hataları alabilirsiniz.

Peki 16 çekirdekli bir işlemci kaynağının olduğu bu ortamda yukarıdaki hata neden alınıyordu dersiniz? Sağolsun birisi ne hikmetse bu ayarı "255" olarak değiştirmiş. Bu nedenle havuzda "704" Worker Thread olabilecekken "255" tane var. Yani aslında ortamda yeterli altyapı var; ama el freni kalkık ve SQL Server çığlık ata ata çalışıyor... Haliyle bir Blocking sorunu oluştuğunda, paralel veya uzun süren bir işlem sık ve yaygın olarak çalıştırıldığında yukarıdaki gibi hata mesajlarına rastlamak da olası oluyor.

Sistem yöneticisi, veritabanı yöneticisi, yazılımcı (evet maalesef...), SQL Server yönetimi yapan tüm arkadaşlar! Eğer ne yaptığınızdan emin değilseniz, emin olmadığınız bir ayarı değiştireceğinize lütfen varsayılan haliyle bırakın. O ayarı çok merak ediyorsanız, o ayar sizi çok rahatsız ediyorsa ve farenize hakim olamıyorsanız buyurun Türkçe Microsoft SQL Server forumlarında sorun, ben veya başka bir arkadaşım müsait olduğunda elinden geldiğince cevaplar. Bu yazıda bahsettiğim sadece bir örnek, bunun gibi daha niceleri var. Yapmak istediğiniz değişiklikleri lütfen ne yaptığınızdan emin olduktan sonra yapın.

Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com