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

6 Eylül 2017 Çarşamba

Veritabanı sunucularınızın maliyetleri nasıl azaltılır?

Her sektörden birçok firmaya giriyorum, çıkıyorum. Bazılarıyla sadece sohbet ediyoruz, bazılarıyla kısa dönemli, bazılarıyla da uzun dönemli çalışıyoruz. Her firmanın kendine göre ihtiyaçları var, bununla birlikte sonuç itibariyle tüm şirketlerin hedefleri aşağı yukarı aynı:

Yapılması gereken işlemlerin düşük maliyetle, kesintisiz olarak ve performanslı şekilde tamamlanması. Bu sayede firma çalışanlarının daha verimli çalışmasının ve müşteri memnuniyetinin sağlanması. Verimlilik.

Bu amacı gerçekleştirmek için bazı yöneticiler daha fazla donanım veya personel alımı yapıyor. Bu yatırımlarla sorunun çözülmediğini gördüklerinde ise hayal kırıklığına uğrayıp sorunun o anda kullandıkları üründen kaynaklandığını düşünebiliyorlar.

Benim örneğimde, tahmin edebileceğiniz gibi Microsoft SQL Server'dan bahsediyorum. Bugüne kadar bu konuda birçok yazı (son 1 senedeki yazı1, yazı2, yazı3, yazı4, yazı5, yazı6) yazdım. Bu seferki de çarpıcı bir örnek diye ayrıca paylaşmak istedim.

Aşağıda, bakım ve destek anlaşması kapsamında çalışma yaptığım sunuculardan birine ait işlemci kullanımının grafiğini paylaşıyorum. 

Büyütmek için resmin üstüne tıklayın.
Bu sunucuda 16 CPU Core'u mevcut. Yine bu sunucuda 1 ay içerisinde gerçekleştirdiğimiz performans iyileştirme çalışmaları sonucunda işlemci kullanımını zirve yaptığı zamanlarda bile %70'lerden %10 civarına indirdik. Gün içerisinde ise işlemci kullanımı eskiden %40 civarındayken artık ortalama %2'yi geçmiyor.

Bu çalışmanın sonucuna daha geniş bir kapsamdan bakarsak: 
- Microsoft SQL Server, 2012 versiyonundan beri Core başına lisanslanıyor. Eğer Open Licensing gibi bir anlaşmanız yoksa lisanslama maliyeti Enterprise Edition için Core başına 14,256$, Standard Edition için ise 3,717$ (kaynak). 16 Core'lu bir Enterprise Edition 228.096$ ediyor. Yukarıdaki gibi bir performans iyileştirme çalışması sonucu artık gereken işlemci kaynağı büyük ölçüde azalmış oluyor. Bunun sonucu olarak en basit haliyle işlemci kaynakları %50 azaltıldığında bile doğrudan ve sadece Microsoft SQL Server lisanslamasından 114 bin dolarlık kar sağlanmış oluyor.

- Birçok firmada çok elzem olmadığı halde Enterprise Edition kullanıldığını görüyorum veya bazı projelerin sadece Enterprise Edition'da gerçekleştirilebileceği düşünülebiliyor. SQL Server 2016 + Service Pack 1 ile birlikte birçok Enterprise Edition özelliği artık Standard Edition'a da geldi (konu hakkındaki yazım). SQL Server 2016 ile gayet şık ve iş gören sürekli kullanılabilirlik ve felaketten kurtulma projeleri gerçekleştirebiliyoruz. Yukarıdaki gibi bir performans iyileştirme çalışmasından sonra Enterprise Edition'a geçmeye hiç gerek kalmadan veya Standard Edition'a Downgrade yaparak lisans maliyetlerini neredeyse 4 kat düşürmek birçok senaryo için mümkün. Bir önceki madde üstünden gidecek olursak 8 Core'dan oluşan 114 bin dolarlık Enterprise Edition maliyetini, 8 Core'dan oluşan Standard Edition ile 29,736$'a düşürebiliriz.

- Lisans maliyetinin yanısıra, artık daha az donanım kaynağı gerektiği için donanım maliyetlerini de azaltmış oluyoruz.

- Şirket çalışanlarının gün içerisinde verimli çalışabildikleri 2-3 saati en verimli şekilde kullanabilmeleri sağlanmış oluyor. Daha az zamanda, daha çok iş gerçekleştirilebiliyor.

- Nihai olarak son kullanıcı olan müşteriler de memnun oluyor.

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

1 Ağustos 2017 Salı

Sahadaki sunucu sağlık-kontrolü tecrübelerimden birkaç kesit

Uzun zamandır sahada, şirketlerin en kritik Microsoft SQL Server sunucularında sağlık-kontrolü çalışmaları yapıyorum. Şirketler bu çalışmayı başlıca şu nedenlerle talep ediyor:

- Kurulum en iyi pratiklere göre yapılmamış, vakti zamanında bir yazılımcı veya sistem yöneticisi "ileri" düğmesine tıklayarak yapmış kurulumu,
- Nedeni net olarak anlaşılamayan ve veritabanından kaynaklandığı tahmin edilen performans sorunları var,
- Veritabanı sunucusu uzun zamandır kendi kendine, bir şekilde çalışıyor, ama acaba her şey gerçekten de yolunda mı diye merak ediliyor ve bir bilenin kontrol etmesi isteniyor.

Şunu belirtmekte fayda var, veritabanı yöneticisi pozisyonu illa her şirkette olmak zorunda olan bir pozisyon değil. Çünkü birçok şirketin tam zamanlı olarak bir veritabanı yöneticisi çalıştırması gerekmiyor, bu nedenle bir süre varolan personel kaynağıyla durum idare ediliyor; özellikle KOBİ'ler için bu hem maliyet, hem de fayda açısından makul olmayabiliyor. Bununla birlikte veritabanı sunucularınız olduğunda, ki aşağı yukarı her şirketin vardır diyebiliriz, barındırılan veriler illa ki kritik oluyor ve IT yöneticileri bu verilerin sağlığından endişe ediyor.

Şimdiye kadar yaptığım sağlık-kontrolü çalışmalarını 3GB'lık veritabanı sunucularından tutun, 20TB'lık veritabanı sunucularına kadar uyguladım. Bu çalışmalar sayesinde birçok sürpriz ve olası felaket durumlarını ortaya çıkarttım. Bu yazıda bu sürprizlerden bazılarını, özetle de olsa vurgulamak istedim. Böylece belki hiç beklemediğiniz olası sürprizler hakkında sizin de haberiniz olur veya önlem almak için bir algı oluşur.

Senaryo 1:
Şirket yetkilisi veritabanlarının çok önemli olduğunu, finansal veri içerdiğini, güvenlik açısından asla taviz veremeyeceklerini iletti.

Sunucuyu kontrol ederken karşılaştığım en çarpıcı noktalar:
- Veritabanı sunucusunun internete açık olması,
- SQL Server TCP port numarasının varsayılan port numarası olan 1433 olması,
- "sa" kullanıcısının etkin olması ve şifresinin basit olması,
- Error Log dosyasında birçok farklı sunucudan, "admin", "sa" gibi birçok farklı kullanıcı adıyla bu "kritik" olan sunucuya bağlanılmaya çalışılmasıydı.

Bu konuda bilgili ve tecrübeli olanlarınız bunların çok bariz ve temel şeyler olduğunu düşünebilir, ama unutmayın, bunlar bilene kolay...

Senaryo 2:
Çok kritik verileri olan bir başka şirket veritabanı sunucularının sağlık kontrolünü yapmamı istedi, veritabanlarındaki veriler yine finansal açıdan çok kritik.

Sunucuyu kontrol ederken en kritik olan veritabanının yedeğinin en son 2 ay önce alındığını gördüm. Bunu kendilerine ifade ettiğimde, elbette oldukça soğuk bir duş etkisi yarattı.

Senaryo 3:
Uluslararası ortakları olan bir firma ile sağlık kontrolü çalışması yaparken, veritabanı yedeklerinin disk doluluğu nedeniyle uzun zamandır alınamadığını gördük. Maalesef ortamda disk kapasite takibi veya Job'lar hata aldığında bunları izleyecek bir mekanizma yoktu. Bu nedenle kimsenin bu hatalardan haberi olmamıştı.

Senaryo 4:
Bir firmanın kritik bir sunucusunda sağlık kontrol çalışması yaparken sunucuda ortalama olarak eşit şekilde yük yaratması beklenen en kritik iki veritabanından birinin aslında CPU, IO ve RAM kaynaklarının %80'ini kullandığını gördük. Tabii bir sorun olduğu net olarak ortaya çıkmış oldu ve iyileştirme çalışmaları için sistem kaynaklarını beklenenden daha fazla tüketen veritabanına odaklanıldı.

Senaryo 5:
Firmanın en kritik veritabanı sunucusunda performans sorunları olduğu iletildi. Sağlık kontrolü çalışması yaparken, 45 dakika ve daha fazla süren sorgular olduğunu tespit ettim. Kimsenin bu kadar uzun süren sorgular olduğundan haberi bile yoktu. Bu ve benzeri sorguları tespit edip, iyileştirme çalışmaları yaptıktan sonra sorunun büyük bir bölümü çözülmüştü.

Senaryo 6:
Canlı ortam olarak kullanılmak üzere düşünülen bir ortama Always On Availability Groups (AG) kurulumu yapılmıştı. Kurulumun yapılandırılmasını kontrol ettiğimde, kurulumu yapanların bir Listener oluşturmadıklarını gördüm. Kurulumu yapanlar, firmaya Connection String'te Cluster adını kullanabileceklerini iletmişti. Firmaya bunun -malumunuz- böyle çalışmayacağını, dilerse test edebileceğini ve testin hata ile sonuçlanacağını ilettim. Tabii ki test hata ile sonuçlandı. Firma tekrar kurulum yaptırmak istemediğini, bütçe ayıramayacağını söyledi ve firmanın "stand-alone" olan sistemlerini Always On AG ortamına taşıma projesi rafa kaldırıldı.

İlginizi çektiyse sağlık-kontrolü çalışmam hakkında daha fazla bilgi için lütfen buraya tıklayın.

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

17 Temmuz 2017 Pazartesi

Bir içeriden saldırı hikayesi

Geçen hafta bir firmadan bir e-posta aldım, içeriği aynen şöyleydi:

"Elektrik gidip geldi ve SQL Database Recovery Pending moduna geçti. Konu hakkında yardımcı olabilir misiniz?"

Kısa ve öz.

Kendilerini aradım, konuştuk. Gündüz başka işlerim olduğu için, akşam bağlanıp kontrol edebileceğimi söyledim kendilerine. Akşam bağlanıp kontrol ettiğimde ve görüşmelere devam edip durum hakkında daha fazla şey öğrendiğimde ortaya çıkan tablo şöyleydi:

- "Recovery Pending" durumunda olduğu söylenen veritabanı dosyaları "Corrupt" idi, yani bozulmuşlardı,
- Bozulan veritabanı bir muhasebe uygulamasına aitti,
- Bozulan veritabanının yedek dosyaları da bozulmuş durumdaydı,
- Bozulan veritabanının normal şartlarda bağlı olduğu SQL Server Instance'ı silinmişti,
- Bozulan veritabanına ait yedek dosyaları Rar uygulaması ile şifreli sıkıştırılmıştı,
- Bozulan veritabanına ait ulaşılabilen ve çalışır halde olan en güncel yedek 3 ay öncesine aitti.

Sanırım hikayenin aslının ne olduğunu, biraz da dehşete kapılarak tahmin etmişsinizdir. Ben durumun böyle olduğunu gördüğümde, görüştüğüm yetkiliye bu durumun ancak "sinirli" ve "kırgın" bir şekilde işten ayrılan eski bir çalışan tarafından oluşturulabileceğini ilettim. Kendisi de bu senaryoyu onayladı.

Veritabanı dosyaları ve yedekler gerçekten elektrikler birden gidip sunucu kapandığı için mi, yoksa eski çalışan tarafından kasten mi bozulmuştu bilemiyorum, bunun aslını sanırım ancak beni arayan kişi ve işten ayrılan kişi bilir; ama durum içinden çıkılmaz bir haldeydi. Çünkü tüm kontrol sadece o işten ayrılan kişideydi, başka hiçbir yedekleme mekanizması yoktu. Haliyle ben de bir şey yapamadım.

Saldırıları veya felaketleri sadece firma dışından beklemeyin. Paranoyak olun ve herkese düşman gibi nefretle bakın demiyorum elbette, ama gerekli önlemleri aldığınızdan emin olmalısınız. İnsanların niyeti iyi veya kötü olabilir, siz her türlü niyet ve senaryo için olabildiğince hazırlıklı olmalısınız. Aksi takdirde kendinizi yukarıdakine benzer bir senaryonun oyuncularından biri durumunda bulabilirsiniz.

Not: Bir çözüm üretemediğim, müşteriyi memnun edemediğim işlerden ücret talep etmiyorum. Fakat en azından harcadığım o kadar zaman ve emek için bir teşekkür beklemek sanırım hakkım. Maalesef bu firmadaki yönetici arkadaş bunca inceleme ve harcanan zaman sonrası gönderdiğim durum raporuna cevap bile vermedi. Yine maalesef, bu örnek tek değil. Bu gibi durumlarda iletişime geçen herhangi bir kişi veya firmaya neden hemen yardımcı olmak istediğimi, bu kadar iyi niyetli yaklaştığımı ciddi ciddi sorguluyorum. Bazıları böyle bir ilgiyi gerçekten, hiç hak etmiyor.

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

11 Temmuz 2017 Salı

"Transaction Log" yedeğinin alınması neden uzun sürebilir?

Son zamanlarda bir ortamda Transaction Log yedeği alınırken yedek alma işleminin 1-2 saati bulabildiğini gözlemledim. Normal şartlar altında 2 dakikada bir yedek alınan ve yedeklerin de ortalama 10MB olduğu bir ortamdan bahsediyorum.

Sorunu incelerken Transaction Log yedek alma işleminin (BACKUP LOG ...) bir sistem işlemi tarafından (o anki "session_id"si 18 idi) bloke edildiğini gördüm. İşler gerçekten ilginçleşiyordu. O sistem işleminin ne olduğunu inceleyince Checkpoint olduğunu gördüm. Açıkçası, Checkpoint işleminin Transaction Log yedek işlemini bloke ettiğini ilk defa görüyordum.

Sorunu daha fazla inceledikçe aslında sorunun disk altyapısında olduğunu tespit ettim. Yani Transaction Log yedek alma işlemi aslında doğrudan kendi başına bir sorun değildi, başka bir sorunun sonucu oluşan bir durumdu.

Aklına "Disk altyapısındaki sorun, Checkpoint ve Transaction Log yedeği ne alaka?" diye soru gelenler için Checkpoint işlemine çok özetle deyineyim. SQL Server'da varolan kayıtlarda değişiklikler yaptığınızda veya yeni kayıtlar oluşturduğunuzda bu değişiklikler doğrudan veritabanı veri dosyalarına işlenmez, önce Transaction Log dosyasına işlenir, daha sonra da belli formüllere göre devreye giren Checkpoint ile bu değişiklikler ilgili veritabanı veri dosyalarına işlenir. Disk altyapısında performans sorunu olunca, Checkpoint ile değişikliklerin diske işlenmesi uzun sürüyordu ve bu da Transaction Log yedeklenmesi işlemini bloke ediyordu. Ben de bu sayede Checkpoint devam ediyorken Transaction Log yedek alınma işleminin sonlanamadığını, bloke olduğunu öğrenmiş oldum.

Biraz kısa bir yazı oldu, ama yine de değerli bir tecrübe olduğunu düşünerek paylaşmak istedim. Olur da bir gün Transaction Log'unun yedeğinin alınması uzun sürerse, disk altyapısının performansını da kontrol etmeyi unutmayın.

Not: Transaction Log ve veritabanı yedekleme işleminin uzun sürmesinin daha başka birçok nedeni var, ama bu yazıda belirli bir konuya değinmek istedim. 

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