
HATA:
The SaveToSQLServer method has encountered OLE DB error code 0x80004005 (Login timeout expired). The SQL statement that was issued has failed.
AÇIKLAMA:
Bağlı olduğum SQL Server Instance'ında bir Maintenance Plan oluşturmaya çalıştığım zaman bu hata ile karşılaştım. Maintenance Plan oluşturmanın son aşamasına kadar geliyordum, en son aşamada plan oluşturulurken plan yerine bu hata oluşuyordu.
ÇÖZÜM:
Planı oluşturmaya çalıştığım SQL Server Instance'ında varsayılan SQL Server TCP portu olan 1433 değil, bizim belirlediğimiz başka bir port numarası kullanılıyordu. Maintenance plan'ı oluşturmak için SQL Server Management Studio ile SQL Server Instance'ına bağlanırken Connect to Server penceresindeki Server name kutucuğunda sunucu adı yazılıydı.
Fakat Additional Connection Parameters penceresinde sunucu adı port numarasıyla birlikte yazılıydı.
Ne zaman ki Connect to Server penceresindeki Server name kutucuğuna sunucu adını port numarasıyla bağlandım, o zaman Maintenance plan'ı başarıyla oluşturabildim.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Bazen müşterilerimden, bazen de forumlarda insanlardan SQL Server'ın hafıza (RAM) kullanımı hakkında benzer soru ve şikayetleri alıyorum: "CPU kullanımı düşükken veritabanı sunucusundaki RAM kullanımının %90 olması normal mi?" veya "SQL Server'da performans sorun var, RAM'in tamamını kullanıyor!".
 |
İnsanları endişelendiren ekranın görüntüsü |
Sorunun kısa yanıtı: "Evet, çok normal ve aslında tam da görmek istediğimiz manzara!"
Bundan sonrası sorunun uzun yanıt kısmı, vakti ve merakı olan okumaya devam edebilir.
Veritabanlarındaki tablolarınızda bulunan kayıtları ilgilendiren bir sorgu çalıştırdığınızda SQL Server öncelikle ilgili kayıtları içeren Page'ler* zaten hafızada mı (Buffer Pool) yoksa değil mi diye kontrol eder, şayet ilgili Page'ler hafızada değilse diske gider ve ilgili Page'leri hafızaya alır. Sonrasında ilgili kayıtlar için işlemler gerçekleştirilir.
* Page, SQL Server'daki en küçük depolama birimidir, 8 kilobayttır ve tablolarınızdaki kayıtlar bu mantıksal birimlerde saklanır.
Hafıza (RAM), disk donanım kaynağına göre çok daha hızlıdır. Bu nedenle SQL Server hafızadan olabildiğince çok faydalanmak ister ve aynı nedenle bir Page diskten hafızaya alındığında, o Page'in olabildiğince makul bir süre hafızada kalmasını isteriz, ki SQL Server sürekli diske gidip tekrar aynı Page'leri hafızaya taşıma işlemi gerçekleştirmesin. En sık kullanılan Page'lerin en makul miktar ve sürede hafızada kalması* yararımızadır.
* Bir Page'in ortalama hafızada kalma süresini Performance Monitor'deki "Page Life Expectancy" (PLE) sayacıyla ölçebiliriz.
Eski iyi pratikler PLE değerinin 300 (saniye cinsinden) iyi bir beklenti olduğunu söyler, fakat 300 zamanımızda artık oldukça düşük bir değer. Peki en iyi değer nedir? Herkes için en iyi değer diye bir değer yoktur, bu değer iş yükünüze, uygulamanızın çalışma doğasına, imkanlarınıza/bütçenize ve beklentinize göre değişir. Bununla birlikte, her halükarda beklentimiz ve hedefimiz, Page'lerin olabildiğince uzun süre hafızada kalması olmalıdır.
Varsayılan Ayar
Yeni bir SQL Server Instance'ı kurduğunuzda varsayılan olarak "Max Server Memory" ayarı 2147483647 megabayttır, yani bir anlamda Buffer Pool için "kullanabildiğin kadar RAM'i kullan"dır. Buna SQL Server literatüründe "dinamik hafıza yönetimi" denir.
Kurulumlardan sonra yapılacak ayar değişikliklerinden biri de bu ayarı makul bir değer* ile değiştirmektir. Çünkü aynı sunucu üstünde SQL Server'ın haricinde işletim sistemi ve diğer elzem uygulama ve hizmetlerin de çalışması ve çalışacak her uygulamanın da hafızaya ihtiyacı olacaktır. Varolan hafıza kaynağının tüm bu uygulamalar arasında herhangi bir çatışmaya neden olmayacak şekilde dikkatlice paylaştırılması gerekiyor.
* Makul değer sunucudan sunucuya ve kullanılabilir fiziksel hafıza miktarına göre değişiklik gösterir. Ayrıca ayarlayıp unutmamak, ayardan sonra sürekli izlemek gerekir. Çünkü zamanla ihtiyaçlar değişebilir. Hafıza kaynağımızı atıl şekilde de bırakmak istemeyiz, sanal hafıza (Windows Page File) kullanılmasını da istemeyiz.
Eğer "Max Server Memory" ayarını yapılandırmazsanız veya yanlış yapılandırırsanız o zaman Task Manager veya başka araçlarla sunucuda kullanılan hafıza oranına bakarsanız %100'leri görebilirsiniz*, işte bu hiç istediğimiz bir durum değildir. Çünkü böyle bir manzara uygulamalar arasında hafıza için çatışma yaşandığı veya yaşanabileceği, sanal hafıza alanının kullanımı gibi şeyleri getirir akla. Performans açısından hiç istemediğimiz bir durum.
* Eğer sunucunuzdaki fiziksel hafıza miktarı, sunucu üstündeki veritabanının hacminden daha yüksekse hafıza kullanımının %100'e çıktığını hiç görmeyebilirsiniz de. Misal sunucuda 128GB RAM varsa ve o sunucu üstündeki toplam veritabanı boyutu 10GB ise muhtemelen hafıza kullanımınız 15-20GB'ı hiç geçmeyecektir.
En sık kullandığınız kayıtlara ait Page'ler hafızadayken sunucu üstündeki başka bir hizmetin veya uygulamanın veya işletim sisteminin hafıza ihtiyacı nedeniyle SQL Server ile hafıza çatışmasına girdiğini ve bu çatışma sonucunda en yüksek işlem hacminin gerçekleştiği bir vakitte işletim sisteminin hafıza kaynağının bir kısmını diğer uygulamalar ve hizmetlere ayırmak için SQL Server'ın Page'lerinin bir kısmını RAM'den attığını ve bunun sonucunda da SQL Server'ın aşağıdaki hatayı ürettiğini düşünün?
"A significant part of sql server process memory has been paged out. This may result in a performance degradation."*
* Bu bir örnek değil, gerçek hayatta tam da böyle oluyor. Bu durum oluştuğunda bu hatayı SQL Server Error Log ve Windows Application Event Log'ta bulabililirsiniz.
Özellikle kritik veritabanı sunucuları için bu tüylerimizi diken diken eden bir manzaradır. Bu olumsuz sonucu son kullanıcılarınız hemen hissedecektir. Çünkü bu durumda uygulamalarınız bloklanma, donmalar ve yavaşlıklar yaşarlar ve bunların sonucunda uygulamalarınız zaman aşımı hataları alabilir. Sonuç olarak ciddi ve düzensiz performans sorunları yaşarsınız ve performans açısından istikrarsız bir ortamınız olur.
Windows Local Security Policy'deki "Lock pages in memory" ayarı sayesinde işletim sisteminin SQL Server'ın Page'lerine müdahale etmesini engelleyebilirsiniz. Fakat yukarıdaki açıklamalardan görebileceğiniz üzere bu sandaldaki bir deliği tıkar, diğer deliğin açılmasına neden olur. Çünkü belli ki bir hafıza ihtiyacı var ve bu bir şekilde karşılanmalı, gerekiyorsa Windows Page File kullanılarak. Diğer hizmet sunucularını bilemiyorum; ama şahsen ben sunucumdaki Windows Page File'ın rutin olarak kullanıldığını görmek istemem.
Bazen...
Bazen tüm yapılması gereken ayarları yaptıktan sonra bile zaman zaman Page Life Expectancy değerinin birden dip yaptığını, misal 100'lerin altına kadar indiğini görebilirsiniz. Böyle anlarda eğer bir takip mekanizmanız varsa veya bilgisayar başından anlık olarak kontrol edebilirseniz ender çalışan, oldukça büyük tablolardan oldukça yüklü miktarda verilerin çağrıldığı masraflı bir sorgunun çalıştığını görebilirsiniz. Özellikle karışık iş yüklerinin olduğu* ortamlarda bu durumla karşılaşılabilinir.
* Hem OLTP işlemlerin hem de raporlama işlerinin çalıştığı ortamlar.
Eğer ortam kritik bir veritabanı ortamı ise farklı raporlama tasarım ve çözümlerini masaya getirmekte fayda olabilir, ki böylece ortam OLTP iş yükü için çok daha homojen hale getirilebilir ve böylece ortamın performans açısından çok daha istikrarlı olması sağlanabilir; fakat bu tamamen farklı bir yazının konusu.
Sonuç
Sonuç itibariyle:
- SQL Server veritabanlarınızdaki tablolara ait kayıtları olabildiğince uzun süre fiziksel hafızada tutmak istersiniz,
- Bunun için Performance Monitor'deki "Page Life Expectancy" sayacının değerini en azından birkaç gün izleyip doğru noktada olup olmadığınızı ölçebilirsiniz,
- Bunları sağlamak için de sunucunuzda yeterli miktarda fiziksel hafıza kaynağı bulunduğundan ve kurulumdan sonra SQL Server'ın "Max Server Memory" ayarını yapılandırdığından emin olmalısınız.
Veritabanı sunucularınızı her zaman yakından takip etmenizi öneririm, çünkü her an, her şey değişebilir. Veritabanını kullanan uygulamalarınızdaki kodlar, iş birimlerinizin ihtiyaçları, kampanyalar, fiziksel/sanal ortamlarınızdaki altyapı değişiklikleri veritabanı sunucularınızın performansını etkileyen başlıca faktörlerdir. Eğer sunucularınızı sürekli izlerseniz, anormal bir durum karşısında hangi değerin normal, hangisinin anormal olduğunu rahatlıkla ayırt edebilir ve doğrudan anormalliklere odaklanabilirsiniz.
Microsoft SQL Server veritabanı sunucularınızında sorun mu yaşıyorsunuz? Size yardımcı olabilirim!
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
4 Kasım tarihinde Microsoft tarafından SQL Server 2019'un RTM olduğu duyuruldu. SQL Server 2019 olmadan önce tabii ki önizleme versiyonları yayınlanmıştı, bu nedenle birçok özelliğini öncesinde deneyimleyebildik. SQL Server 2019 RTM olmadan hemen önce hangi özelliklerin sadece Enterprise Edition'da, hangi özelliklerin Standard Edition'da olacağını öğrenmiştik. Artık ürün RTM olunca, yani her şey netleşince, SQL Server 2019 Standard Edition ile yeni gelen özelliklerden ve eski Enterprise, yeni Standard Edition özelliklerinden bazılarından özetle* bahsedeyim istedim.
* Ancak özetle bahsedebileceğim, çünkü her özelliğin ayrıntıları deniz derya. Standard Edition'daki tüm yeni özelliklerin duyurusuna buradan ulaşabilirsiniz.
Ek Bilgi: Software Assurance müşterileri için yine son günlerde duyurulan sürekli kullanılabilirlik ve felaketten kurtarma seçeneklerine dair lisanslama kolaylığını LinkedIn'de paylaşmıştım. Görmeyenler için buraya da not etmiş olayım.
Öncelikle SQL Server'ın önceki versiyonlarında da olan, fakat sadece Enterprise Edition müşterilerinin kullanabildiği ve SQL Server 2019 ile birlikte Standard Edition'da da kullanılabilen özelliklerden bahsedeyim.
Transparent Database Encryption (TDE): Bu özellik SQL Server 2008'den beri var ve bununla verilerimizi barındıran dosyaları diskte şifrelemiş (encryption) oluyoruz. Ayrıca veritabanı yedek dosyalarımız da otomatik olarak şifrelenmiş oluyor. Böylece veritabanımıza bir Login veya uygulama açığı ile giremeyip, veritabanı dosyalarımıza ulaşabilecek kötü niyetli kişiler, bu dosyaları alsalar dahi gerekli sertifikalar olmadan verilere ulaşamıyorlar. Güvenlik açısından oldukça önemli bir özellik.
Always Encrypted with secure enclaves: Veritabanınızın bulunduğu bir SQL Server Instance'ında "sysadmin" üyesi bir Login, özelleştirilmiş bir şifreleme yöntemi kullanmadığınız müddetçe o Instance'taki tüm veritabanlarındaki tüm verilere ulaşabilir. Always Encrypted özelliği ilk defa SQL Server 2016 Enterprise Edition ile gelmişti. Bu özellik sayesinde kritik olan veriler sütun bazında şifrelenebiliyor, uygulamalar ihtiyaç duydukları verileri veritabanından çekerken veya veritabanına işlerken şifrelemeyi kendi taraflarında uyguluyorlar. Veritabanı yöneticisinde veya kötü niyetli kişilerde ilgili sertifikalar olmadan şifreli veriler deşifre edilemiyordu. Bu özelliğin bu versiyonunun bazı sınırlamaları vardı, örneğin sorgunuzla bir veriye ulaşmak istediğinizde "=" kullanmanız gerekiyordu, belli desenlere göre (WHERE ... LIKE ...) veya büyüktür, küçüktür operatörleriyle arama yapamıyordunuz.
Microsoft "secure enclaves" eklentisiyle bu sorunları çözmeyi hedefliyor. Çünkü bu kısıtlar bu özelliğin kullanımını sınırlayan kısıtlardı. "secure enclave" sunucu tarafında, SQL Server kapsamında, güvenli bir hafıza bölümünde SQL Server Database Engine içerisindeki şifrelenmiş hassas verileri düz metin olarak işleyen bir güvenli ortam.
 |
Bu grafiği yukarıda adresini verdiğim sayfadan aşırdım. |
Açıkçası o kadar şirkete girip çıkıyorum, onlarca sunucunun yönetimine destek oluyorum henüz hiç bu özelliği kullananı görmedim de, duymadım da. Tabii bunun haklı nedenleri var. Öncelikle TDE gibi oturmuş bir özellik değil, henüz yeni. Bu versiyonda da gördüğümüz gibi eklemelerle eksiklikleri giderilmeye çalışılıyor. Bununla birlikte -korkutmak gibi olmasın ama- TDE gibi "oturmuş" dediğimiz özelliklerde bile zaman zaman korkunç
Bug'lar oluşabiliyor. Sonuç itibariyle denediğiniz bir özellik doğrudan verinizi etkiliyorsa, gerçekten çok temkinli olmakta, dünya çapında literatürü takip edip, bol bol mümkün olduğunca çok senaryoyu içerecek testler yapıp özelliğin yan etkilerini iyi anlamak çok çok çok önemli. Ne kadar vurgulasak az.
Aklınıza "Peki TDE ile Always Encrypted arasındaki temel fark nedir?" sorusu gelmiş olabilir, hemen cevaplayayım. TDE veritabanınızdaki verinin tamamını* diskte (at rest) şifreler, Always Encrypted ile ise veritabanınızdaki belli bir tablonun belli sütunlarını şifrelersiniz. TDE kullandığınızda "sysadmin" rolünün üyesi biri o veritabanındaki verilere ulaşabilir; fakat Always Encyrpted'ta bu mümkün değil**.
* Veritabanınızın tempdb'yi kullanma olasılığına karşın tempdb'yi dahi şifreler, ta ki Instance'taki en son TDE özelliği açık veritabanı kalmayıncaya kadar.
** Sertifika olmadıkça.
Accelerated Database Recovery (ADR): Sanırım 1 ay önceye kadar kimse bu özelliğin Standard Edition'a geleceğini tahmin edemezdi. Çünkü çok "Enterprise Edition" kokan bir özellik. Yeterince tecrübesi olanlarınız muhakkak yaşamıştır, çok uzun süren ve veri değişikliği yapan bir sorguyu durdurduğunuzda veya tam o esnada Database Engine servisini (çeşitli korkunç nedenlerle) yeniden başlattığınızda Rollback'in / Recovery sürecinin tamamlanmasını beklemek tam bir işlence olabiliyor. Bunun en kötü örneklerinden birini sanırım 2010 senesinde yaşamıştım, çok kritik bir uygulamamızı barındıran SQL Server 2000 (evet, biliyorum...) Instance'ındaki Rollback 8 saat sürmüştü. Tam bir cehennem.
ADR sayesinde Rollback / Recovery süreçleri anında sonlanıyor. Laf olsun diye "anında" demedim, gerçekten anında sonlanıyor. Bunun nasıl olduğunu merak edenler bu başlıkta paylaştığım dokümantasyona bakabilir.
Intelligent Query Processing (IQP): Bu özellik ailesindeki her bir özellik değil, ama bazıları Standard Edition'a da geliyor. Bu bazılarından en öne çıkanı ve dünyada en çok ses getireni "Intelligent Database: scalar UDF inlining" özelliği oldu. Yazılımcı arkadaşlar User Defined Function (UDF) kullanımını sever, çünkü kodu bir kere yazarsın ve birçok yerde kullanabilirsin, ayrıca kodu okumayı da kolaylaştırır, çünkü o UDF içerisinde ne olduğunu zaten bilirsin. Fakat SQL Server Query Optimizer açısından UDF kullanımı sıkıntılıdır. Örneğin bir sorguda UDF kullanıldığında o sorgu paralel çalışamaz ve sorgunun çalıştırma planında UDF ile ilgili performans sorununu göremezsiniz. "Intelligent Database: scalar UDF inlining" sayesinde ise UDF'i çağıran sorgu içerisinde UDF sanki elle yazılmış kod gibi açılır, yani yukarıda saydığım olumsuz durumlar ortadan kalkmış olur.
Diğerleri için ilgili
dokümantasyonu inceleyebilirsiniz.
Şimdilik bu kadar. Bu yazı ile maksadım sizleri SQL Server 2019 ve Standard Edition'daki yeni özelliklerden genel olarak haberdar etmek, bazı yenilikleri de vurgulamaktı. Umarım faydalı olur.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Birkaç aydır kendi ürünüm olan Microsoft SQL Server ortamları için veritabanı izleme uygulamam Kangal'ın yeni major versiyonuna son halini vermek konusunda ve bir yandan da müşteri ortamlarının ihtiyaçları ve yeni projeler konusunda çalışıyorum. Son gelişmelerden sonra bir tecrübeyi paylaşmak istedim.
Kangal'ın yeni versiyonuna SQL Injection saldırılarını yakalayacak yeni bir özellik ekledim. Pilot ortamlarda başarılı sonuç elde ettikten sonra ilgili güncellemelerin tüm müşteri ortamlarına da akmasını sağladım.
Yeni versiyonun pilot süreci devam ederken bu özellik bazı müşterilerde zaman zaman alarm üretiyordu, alarm geldiğinde ilgili IT yöneticisine bu alarm için gelen e-postaya cevaben "planlı bir pentest çalışması mı yapılıyor?" diye soruyordum ve "evet" cevabını alınca hayatımıza devam ediyorduk. Bu ortamlardan birinde, bir müşteriden gene alarm geldi. Her zamanki gibi IT yöneticisine yine bir pentest çalışması olup olmadığını sordum ve "hayır" cevabını aldım. Tabii o anda hemen yangın zilleri çalmaya başladı; IT yöneticisi, Yazılım Müdürü ve hatta Genel Müdür, bu saldırıdan haberdar olması gereken herkese ulaştım. Sorunun üstünde hepbirlikte çalıştık, yazılım tarafındaki açıklar tespit edildi ve en kısa sürede soruna müdahale edilip bertaraf edilmiş oldu.
 |
Saldırı esnasında Kangal'ın ürettiği alarmlardan bir örnek |
SQL Injection saldırısı nedir?
Özellikle dinamik SQL kullanılan uygulamalarda, arayüzlerde gerekli korunma önlemleri de alınmadıysa, uygulamaların ürettiği SQL cümleciklerinin arasına veya sonuna "enjekte edilen"/eklenen SQL cümlecikleriyle veritabanlarınıza ve hatta veritabanı sunucunuza saldırganların müdahale edebilmesidir çok özetle. Bunun nasıl yapılabileceğine dair internette oldukça fazla kaynak mevcut.
Bu sorunu fark edemeseydik neler olabilirdi?
Saldırganlar veritabanımızda birçok şey yapabilirlerdi. Örneğin görmelerini istemediğimiz verileri görebilirlerdi, kayıtlarda değişiklikler yapabilirlerdi, tablolarımızı ve hatta veritabanlarımızı silebilirlerdi, hatta disklerimizi formatlayabilir, sunucumuzu kapatabilirlerdi, ki saldırgan arkadaş bunu da denedi.
Neler yapabilecekleri, bizim proaktif olarak ne kadar önlem aldığımıza, uygulamamızı ve yetkilendirme politikamızı ne kadar sıkı tuttuğumuza, en iyi pratikleri ne kadar yakından izlediğimize ve ne kadar disiplinli olduğumuza göre değişir. Eğer tüm uygulama kullanıcılarına "sysadmin" veya "db_owner" yetkisi verilen, SQL Server servis hesabı için en iyi pratiklerin uygulanmadığı, Instance seviyesindeki ayarlara önüne gelenin güvenliği düşünmeden müdahale ettiği bir ortam olsaydı, yaşadığımız bu saldırı felaketle sonuçlanabilirdi.
Özellikle küçük ve orta ölçekli şirketlerin böyle saldırıları fark edecekleri mekanizmaları (uygulama ve kalifiye personel) olmuyor. Eğer bu konuda yetenekli bir uygulamanız yoksa bu tür saldırıları fark ettiğinizde oldukça geç kalmış olabilirsiniz. Çünkü bu saldırıda saldırganın çalıştırdığı komutları uygulamanın çalıştırdığı onca komuttan göz kontrolüyle ayıramazsınız. Ancak uygulama hatalarını yakalayan bir mekanizmanız varsa ve mekanizmanın yakaladığı anormallikler konusunda sizi uyaran alarmlar varsa bu saldırıyı böyle yakalarsınız ya da saldırıyı vakitlice fark edemezsiniz ve ancak saldırının sonuçları sayesinde saldırıdan haberdar olursunuz, ki bu da hiç hoş bir deneyim olmaz.
Kangal uygulamalarınızın veritabanına karşı çalıştırdığı SQL kodlarına dair tüm hataları takip eder. Bir hata oluştuğunda bu hataya dair ayrıntıları kayıt altına alır. Yeni eklenen SQL Injection koruma özelliği sayesinde de bu üretilen hataları analiz eder ve olası SQL Injection saldırılarına karşı tüm ekibinizi uyarır. Olası saldırılar veya uygulama hatalarınız hakkında en kısa sürede, ayrıntılı bir şekilde haberdar olmuş olursunuz.
Kangal'a eklenen yeni özelliklerden bir diğeri de veritabanı yedeklemesi ile yapılan veri hırsızlığına karşı izleme yapması ve alarm üretmesi. Bu konuya da bir dahaki yazımda değineceğim.
Meraklıları için İpucu:
Eğer benzer bir uygulamayı kendi olanaklarınızla kendi ortamlarınızda yapmak isterseniz bunu Extended Event'lerle yapabilirsiniz. Extended Event'in "error_reported" adında bir Event'i var. Bu Event ile SQL hatalarını kayıt altına alabilir, bu kayıtları taratıp anormallikleri raporlatabilirsiniz.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
SQL Server ile belli bir tecrübesi olan herkesin bildiği gibi bir T-SQL komutunu çalıştırdığınızda, bu komut için önce bir çalıştırma planı (Execution Plan) oluşturulur, bu plan Plan Cache'te depolanır* ve komutunuz bu plana göre** çalışır.
* "Optimize for ad-hoc workloads" ayarı devrede olduğunda ad-hoc sorgular için çalıştırma planının tamamı depolanmaz Plan Cache'te, yalnızca "Stub" denilen küçük bir bölümü depolanır. Böylece Plan Cache bir daha muhtemelen kullanılmayacak binlerce plan ile dolup taşmaz.
** İstisnai durumlarda yolda plan değişebilir, işte bu nedenle Estimated Execution Plan ile Actual Execution Plan farklı olabilir.
Belli bir Batch veya stored procedure için Plan Cache'teki çalıştırma planını görmek istediğimizde sys.dm_exec_query_plan isimli DMV'den faydalanabiliriz. Örneğin:
SELECT [query_plan] FROM sys.dm_exec_query_plan();
komutuyla X isimli stored procedure'ün plan handle'ını sorgulayıp çalıştırma planını aldığınızı düşünün. Eğer bunu yeterince çok denediyseniz, ilgili sorgunun planının Plan Cache'te olduğundan emin olduğunuz halde yukarıdaki sorgunun zaman zaman null değeri döndüğünü görmüşlüğünüz olmuştur. Bu yazımda bunun nedenini açıklamak istedim.
Bir stored procedure içerisinde temp table kullanılıyorsa, sorgu belli koşullara göre birkaç seçenek içeriyorsa veya "RECOMPILE" seçeneği ile çalıştırılıyorsa o zaman deferred compilation denilen olay gerçekleşiyor ve SQL Server stored procedure ilk defa çalıştırılırken sorgunun tamamı için çalıştırma planı oluşturmuyor.
sys.dm_exec_query_plan isimli DMV çalıştırma planını bir bütün olarak getiriyor. Ya hep, ya hiç. Eğer Batch'inizdeki veya stored procedure'ünüzdeki tüm bloklar için çalıştırma planı varsa*, o zaman bu DMV ile ilgili sorgunuza dair oluşturulan çalıştırma planını Plan Cache'ten edinebilirsiniz.
* SQL Server 2005'ten beri Batch içerisindeki tüm kod blokları için ayrı ayrı çalıştırma planı üretiliyor.
Peki Batch'inizde veya stored procedure'ünüzde deferred compilation nedeniyle henüz çalıştırma planı olmayan komutlar varsa, ama siz olduğu kadarını görmek istiyorsanız ne yapacaksınız? sys.dm_exec_query_plan DMV'si bu durumda null sonucunu döner, işte bu durumda sys.dm_exec_text_query_plan isimli DMV'yi kullanmalısınız.
sys.dm_exec_text_query_plan isimli DMV'yi kullanırken eğer "statement_start_offset" ve "statement_end_offset" değerlerini girmezseniz yine sys.dm_exec_query_plan DMV'si ile yaşadığınız sorunu yaşarsınız. Bu nedenle bunu atlamamanız önemli.
Örnek kullanım:
SELECT
CAST([qp].[query_plan] AS XML) AS [query_plan],
[qs].[execution_count],
...
FROM sys.dm_exec_query_stats AS [qs]
CROSS APPLY sys.dm_exec_text_query_plan ([qs].[plan_handle], [qs].[statement_start_offset], [qs].[statement_end_offset]) AS [qp]
WHERE OBJECT_NAME([qp].[objectid], [qp].[dbid]) = 'sp_adı';
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Query Store'u (QS) neredeyse ilk çıktığından beri kullanıyorum. Doğru ayarlarla kullanıldığında oldukça faydalı olabilecek bir özellik. Microsoft'a bunun için teşekkürler!
QS'un nasıl etkinleştirildiğini veya nasıl ayarlanması gerektiğini internetten rahatlıkla bulabilirsiniz. Benim bu yazı ile size anlatmak istediğim ise yönettiğim bir ortamda QS ile yaşadığım tatsız tecrübelerin özet bir derlemesi.
Önce sorun yaşadığım ortam hakkında biraz bilgi vereyim. Veritabanının boyutu 2TB civarında, çalıştırılan kodlar veritabanında tutulmuyor, yani Stored Procedure ve saire yok. Sorgular uygulama tarafından dinamik olarak oluşturuluyor, bazıları parametreli, bazıları doğrudan değerleriyle birlikte geliyor.
Böyle bir veritabanı için QS dahili veritabanına 10GB alan tanımladım, biriken veriyi de en fazla 1 gün tutsun istedim; ama iş yükünün, sorguların doğası ve yaptığım izleme ayarı (monitoring) gereği bu alan yeterli gelmedi. 20GB'ı denedim olmadı, en son 25GB'ta bıraktım ve bunun bile zaman zaman yetmediğini gördüm. Bazen bakıyorum QS Read/Write modunda, bazen bakıyorum Read Only moda geçmiş, ki dahili veritabanı alanı yetmediğinde QS Read Only moda geçer.
Bu dahili QS alanını çok büyük tutmak istemiyordum, çünkü önceden nahoş tecrübeler yaşamıştım. QS'in Garbage Collector'ü eski kayıtları silerken Blocking'e ve yavaşlıklara neden olabiliyor. Bunun yanısıra maalesef ispatlayamıyorum*; fakat QS'in dahili ve kontrol edemediğimiz bakım işlemleri sırasında Resource Semaphore sorununa neden olduğunu gözlemledim.
* Bir sorunun nedenini net kanıtlarla açıklayamamak gerçekten utanç verici ve beni çok rahatsız eden bir durum. Fakat uygulamanın açık kaynak kodlu olmadığını, bu özellik hakkındaki dokümantasyonun sınırlı olmasını ve tüm ayrıntılara ulaşamadığımızı göz önünde bulundurmanızı rica ediyorum.
Bu yan etkilerin yanısıra, QS'un etkin olduğu veritabanının Database Engine servisini yeniden başlattığımda canlı veritabanının gelen sorguları kabul etmediğini, sorguların zaman aşımı hataları aldığını gördüm. Sorguların bekleyişine dair ekran görüntüsünü aşağıda görebilirsiniz. Bu sorunun nedeninin ise, QS'un dahili veritabanı yüklenirken bu işlemi varsayılan olarak "senkron" modda yaptığını, bunun varsayılan ayar olduğunu, bu dahili veritabanı yüklenirken de canlı veritabanının hiçbir sorguyu kabul edemediğini gördüm. Bu anın ekran görüntüsü aşağıda.
 |
QS açılışı |
Dahili QS veritabanının 25GB olduğunu ve 2TB'lık canlı veritabanının içerisinde önce bu 25GB'lık veritabanının yüklenmesi gerektiğini, canlı veritabanınızın ancak bu yükleme işlemi bittikten sonra sorgu kabul edebileceğini düşünün. Kritik bir ortamda bu hiç de hoş bir durum değil. Bu konuda araştırma yaparken başka bir arkadaşın bu yükleme sırasında 3 saat beklediğini gördüm! Felaket.
Neyse ki 7752 kodlu bir Trace Flag (TF) mevcut. Bu TF, QS'un yüklenmesinin asenkron şekilde yapılmasını sağlıyor. Bu sayede örneğin Database Engine servisi yeniden başladığında ve canlı veritabanınızın Recovery işlemi tamamlanır tamamlanmaz, QS'un dahili veritabanının yüklenmesinin bitmesini beklemeden canlı veritabanınız sorguları kabul etmeye başlıyor ve QS veritabanının yüklenmesi arkaplanda ve asenkron olarak devam ediyor.
Notlar:
- QS ile ağırlıklı olarak Stored Procedure kullanılan ortamlarda benzer bir sorun yaşamadım.
- Veri ve işlem hacmi düşük olduğunda muhtemelen gelen sorgular ağırlıklı olarak dinamik SQL olduğu halde sorun yaşamayacaksınızdır.
- QS ile ilgili yaşayacağınız olası sorunlar, veritabanına gelen iş yükü ve yükün doğasına göre değişkenlik gösterebilir.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
SQLBits uzun yıllardır İngiltere'de gerçekleştirilen bir SQL Server etkinliğidir, Microsoft ve uluslararası topluluk bu etkinliğe oldukça ilgi gösterir. Bu etkinliğin sonuncusu 27 Şubat - 2 Mart 2019 tarihleri arasında gerçekleştirildi. Bu yazımda etkinlik boyunca sergilenen oturumlarda benim dikkatimi çeken konular hakkındaki notlarımdan bazılarını sizlerle de paylaşacağım.
Not: Bu etkinliğe fiziksel olarak gitmediğimi, oturumları uzaktan izlediğimi belirteyim. Yani bunu siz de yapabilirsiniz. Oturumların kayıtlarına buraya tıklayarak ulaşabilirsiniz.
Not: Etkinlik sırasında SQL Server 2019'un CTP 2.3'ü yayınlandı.
1- Sunuculuğunu Buck Woody'nin üstlendiği açılış konuşmasında Bob Ward'tan SQL Server 2019 ile birlikte artık sistem veritabanlarının da Always On Availability Groups'a katılabileceğini öğrendim. Bu sayede Instance seviyesindeki Login, Job ve benzeri nesneler de ikincil sunuculara otomatik olarak aktarılabilecek. Bunu Script'lerle yapmak gerçekten pek eğlenceli değildi, nihayet bu özelliğin geliyor olduğunu bilmek güzel. CTP 2.3'te yok, ama gelecek CTP'lerde görecekmişiz.
2- SQL Server 2019 ile birlikte
"String or binary data would be truncated." *
hata mesajının çok daha anlamlı bir hale getirileceğini zaten duymuştuk; ama tam olarak nasıl olacağını ben bilmiyordum.
* Bilmeyenler için, bu hata mesajı örneğin 20 karakter uzunluğundaki bir metin alanına 21 karakterlik veri yazmak istediğinizde oluşur. Eğer bu işlemi yaptığınız kod bloğu içerisinde, ki SP veya toplu bir komut olabilir, tam olarak hangi kod satırındaki hangi tabloda hangi alanda işlem yaparken bu hatanın oluştuğunu bilemezsiniz ve bu sıkıcı bir "debug" çalışmasıdır.
Bu hata mesajının yeni biçimi şöyle oluyor
"String or binary data would be truncated in table 'tablo adı', column 'sütun adı'. Truncated value: 'değer'."
Nihayet! Hatta bunun için SQL Server 2017 ve 2016'ya kadar geriye dönük güncelleme çıkacaklarmış. Bu konuda Microsoft'un bir blog yazısını da buldum, okumak isteyenler buyursun.
3- Tempdb'de de güzel bir değişiklik var. SQL Server 2019 ile birlikte artık bu sistem veritabanındaki tüm sistem tabloları in-memory OLTP "Schema_Only" olarak oluşturulacak. Böylece sistem tablolarında Latch Contention sorunu oluşmayacak. Sonuçta tempdb yeniden başladığında boş olarak başlıyor, yani verinin kalıcı olmasına (durability) ne gerek var? Şu anki CTP 2.3'te yok bu özellik, ama gelecek CTP'lerde görecekmişiz.
4- Yine SQL Server 2019'da Accelerated Database Recovery (ADR) adında yeni bir özellik geliyor. SQL Server ile özellikle yoğun ortamlarda çalışanların ve yöneticilerin illa tecrübe ettiği bir hadisedir, çok uzun bir veri değişikliği sorgusu çalışır, bunun sahayı felç ettiği biraz geç anlaşılır, sonra yukarıdan büyük baskı gelir ve sorunlu sorgu tespit edilir ve durdurulmaya çalışılır; fakat sorgu durur mu? Durmaz. Çünkü Rollback süreci başlamıştır. Duruma göre bu oldukça uzun bir süre devam edebilir ve bu süreçte Blocking'ler, ciddi yavaşlıklar gibi sıkıntılar yaşanabilir. Hatta bazıları umutsuzca SQL Server Database Engine servisini yeniden çalıştırmayı dener, tabii ki bu beyhude bir girişimdir, çünkü Recovery süreci tamamlanmadan eski mutlu günlere dönemezler. İşte SQL Server 2019 ile birlikte gelecek olan ADR tüm bu sorunları çözüyor. Tabii ki her şeyin bir bedeli var, ADR'ın da. Bunun için bir çeşit "row versioning" yöntemi kullanılmış, ama SQL Server 2005 ile birlikte gelen gibi değil, çünkü ADR'ın Database Engine servisi yeniden başlatıldığında da işe yaraması gerekiyor; ama malum servis yeniden başladığında tempdb sıfırlanıyor, bu nedenle işe yaramaz. İşte bu yüzden ADR için "row versioning" işlemi ADR'ın etkinleştirildiği veritabanının içinde gerçekleştiriliyor, tempdb'de değil. Geçen gün Brent Ozar bunun demosunu yayınlamıştı, merak edenler buyursun.
5- Profesör Mark Whitehorn'un "Graph databases - What, how and why" isimli sunumunu çok keyifli bulduğumu belirtmek isterim. Konuyu SQL Server özelinde değil, genel olarak "Graph Database" modeli çerçevesinde anlatıyor; fakat sonuç itibariyle Node'lar, Edge'ler ve bunların birbiriyle ilişkisi. O yüzden birebir alakalı.
6- Microsoft'ta Program Manager olarak çalışan Pedro Lopez sunumunda ISV'lere uygulamalarınızı SQL Server versiyonuna, bulut veya on-prem olmasına göre değil, SQL Server Compatibility Level'a göre sertifikalandırın diyor. SQL Server versiyonunu yükselttiğinizde uygulamanın performansının daha kötü olabileceğinden çekinerek versiyon yükseltmemeyi düşünmeyin, misal bir uygulama veritabanı sunucusunu SQL Server 2012'den SQL Server 2016'ya yükselttiğinizde eğer veritabanının Compatibility Level'ını SQL Server 2012 seviyesine getirirseniz veritabanınızdaki kodlar yine SQL Server 2012'deki performansla çalışacaktır diyor (mealen). Çünkü yeni versiyonlarda Query Processor'da yapılan performans ile ilgili geliştirmeler ancak Compatibility Level'ın değiştirmesiyle devreye giriyor. Pedro Lopez Microsoft'un ISV'lerin sertifikalandırma konusundaki bakış açısını değiştirmek için çalışmalara devam ettiğini, hatta Sharepoint'in gelecek versiyonunun da bu şekilde sertifikalandırılacağını söylüyor.
Bununla birlikte "discontinued feature" olarak adlandırılan özelliklerin Compatibility Level'dan bağımsız olarak yeni versiyonlarda çalışmayacağını vurgulamakta fayda var. Örneğin SQL Server 2012'de Discontinued Feature olarak belirlenen bir özellik, veritabanını bir SQL Server 2019 Instance'ına taşıdıktan sonra Compability Level'ı 110 da yapsanız çalışmayacaktır. Bu nedenle versiyon yükseltme çalışmasının ön analizini dikkatlice yapmalısınız.
"Deprecated" özellikler ise Compability Level Protection kapsamında yeni versiyonlarda da desteklenmeye devam ediyor, yani SQL Server 2012'de "Deprecated Feature" listesine giren bir özellik, veritabanı sunucunuzu SQL Server 2019'a yükseltseniz bile Compability Level'ını 110 olarak ayarladığınızda çalışmaya devam ediyor.
7- SQL Server on Linux ilk duyurulduğunda hemen bir VM oluşturmuş, üstüne Ubuntu kurmuş ve SQL Server 2017'yi de onun üstüne kurup Host'taki SQL Server Management Studio'dan Ubuntu kurulu VM'deki SQL Server 2017'ye bağlanmış ve bunun da yazısını yazmıştım. Fakat Container nedir, SQL Server ile neden ve nasıl kullanılır açıkçası pek bilgim yoktu. Bob Ward'un "Inside SQL Server Containers" isimli oturumunu izlediğimde ise oldukça güzel bir resim oturdu kafamda. Bir veya daha fazla imajdan bir veya daha fazla Container'ın nasıl çalıştırılabileceğini, nasıl saniyeler içerisinde SQL Server'ın güncellenebileceğini veya daha üst bir versiyona yükseltilebileceğini, neden farklı imajlar oluşturmak isteyebileceğimi, Container kapandığında veritabanlarımı kaybetmemek için neler yapabileceğimi ve ne gibi senaryolarda SQL Server'ı bir Container'da (misal Docker) çalıştırmak isteyeceğimi öğrendim. Eğer bu konuda merakınız varsa, bu oturumu kaçırmamanızı özellikle tavsiye ederim.
Not: Bu oturumun seviyesi 400'dür. Yani ileri seviye.
Önemli hatırlatma:
SQL Server 2008 ve SQL Server 2008 R2 versiyonları için Microsoft Extended Support Temmuz 2019'da bitiyor, yani 4 ay kaldı. SQL Server veritabanı sunucularınızın SQL Server'ın yeni versiyonlarına Microsoft'un önerilerine %100 uyumlu olarak, ama saha tecrübesini de göz ardı etmeden yükseltilmesi, bu yükseltme çalışmasının en verimli, risksiz, hızlı ve profesyonel şekilde yapılması konusunda desteğe ihtiyacınız varsa lütfen tıklayın. Şirketinizin ihtiyaçlarına en uygun SQL Server Edition'ını birlikte belirleyelim, en düşük lisans maliyetiyle, en kısa kesinti süresiyle ve hiç veri kaybetmeden SQL Server sunucularınızın versiyonunu yükseltelim.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Verilerimizi hem afet durumlarından, hem kişisel veya uygulama kaynaklı hatalardan, hem de içerideki veya dışarıdaki kötü niyetki kişilerden zaten korumak durumundaydık; fakat artık müşterilerimizin veya potansiyel müşterilerimizin verilerini gerek Avrupa Birliğinin GDPR'ı gerekse 6698 sayılı Kişisel Verilerin Korunması Kanunu düzenlemelerini de dikkate alarak korumamız gerekiyor. Aksi durumda şirketlerin çok büyük yaptırımlar ve cezalarla karşı karşıya kalması ve bunların neticesinde iflasa kadar gitmesi maalesef abartılı bir tahmin değil.
Bu tür düzenlemeler ve kanunlar vatandaşlar olarak hepimizin yararına olmakla birlikte gerek bilinçlendirme, gerekse varolan güvenlik düzeneklerimizi tekrar gözden geçirip daha da sağlamlaştırma fırsatı sunma açısından bir bakıma iyi de oluyor bence.
Malum güvenlik ciddi bir konu, fakat çok da maliyetli olabiliyor. Elbette her şirketin şartları, imkanları ve bütçesi farklı. Bazı çözümler çok güzel de olsa, gerek lisanslama gerekse yetkin personel maliyetleri açısından "güzelden soğutuyor". Bu nedenle çözümler zaman zaman şartları zorlayarak, ama genelde de eldeki imkanları kullanarak oluşturuluyor. Şahsen ben eldeki imkanları kullanarak bir şeyler üretmekten çok keyif alırım, bu yazımda özetle bahsedeceğim çözümler de bu bakış açısıyla üretilmiş çözümler. Ayrıca vurgulamakta fayda var, güvenlik sadece teknik önlemlerden ibaret değildir, buna da değineceğim.
Bu konularda hala hiçbir adım atmayan birçok şirket var, ne yazık ki bunlar çoğunlukta. Bazılarının kısmen de olsa bir şeyler yaptığını, azınlık bir kesimin ise iyi hazırlandığını görüyorum.
Bu yazımda başlık başlık ve kısa özetlerle benim yönettiğim Microsoft SQL Server ortamlarında ne gibi önlemler aldığıma, ilgili yöneticilere neler önerdiğime değineceğim.
1- Ortamlarınızı ayırın:
Canlı (live/prod), test (pre-prod/QA/UAT), geliştirme (dev) ortamlarınızı mümkünse ayırın. Geliştirme ortamlarınızdaki verileri tazelerken muhakkak kritik verileri karartın/maskeleyin. Yazılımcılar geliştirme ortamlarında istedikleri testleri yapabilsinler, ki azami oranda canlı ortamda yetkiye ihtiyaçları olmasın.
2- Kod yaygınlaştırma:
Veritabanına kod taşıma işini uygulamalar aracılığıyla gerçekleştirin, eğer bütçeniz yoksa da birinci öncelikli ve ikinci öncelikli kişiler belirleyin, test ve canlı ortamlara kod taşımalarını sadece bu arkadaşlar gerçekleştirsin.
3- Tüm uygulama/vekil kullanıcı bilgilerini kasaya koyun:
Uygulama/vekil kullanıcı bilgileri sağda, solda gezmemeli; Excel dokümanlarında veya postit'lerde veya metin dosyalarında saklanmamalı. Hem güvenlik açısından, hem de operasyonel açıdan kullanıcı adı, şifre ve diğer ayrıntılarının çok güvenlikli bir uygulama ile saklanması gerekiyor. Bu uygulamaya erişim yetkisinin çok sınırlı, ama yeterli sayıda kişide bulunması gerekiyor. Bu kişilerin kimler olduğu da ilgili yöneticiler tarafından bilinmeli, ki gerektiğinde kime ulaşılacağı net olsun.
4- Görevler ayrılığı ilkesi:
Sistem Yöneticisi veya Ağ Yöneticisi bir arkadaşın veritabanında ne işi var? Nasıl ki evimizin anahtarının sadece ilgili kişilerde olmasını istiyorsak, veritabanımıza giriş hakkının da sadece ilgili kişilerde olmasını isteriz.
5- Uygulama/vekil kullanıcılara sınırlama:
Uygulamalarımız için oluşturduğumuz ve adına uygulama/vekil kullanıcı diyebileceğimiz kullanıcıları gerçek kullanıcılar kullanamamalı. Örneğin cep telefonu uygulamaları için oluşturup kullandığımız "mobile_user" kullanıcısını yazılımcı bir arkadaş SQL Server Management Studio uygulamasını kullanarak veritabanına bağlanamamalı. Uygulama/vekil kullanıcıları veritabanına sadece belirli uygulama sunucularından bağlanabilmeli.
6- Anonim kullanıcıya hayır:
Birçok ortamda şirketteki tüm çalışanların "sa", "master", "admin" gibi anonim kullanıcıları kullandıkları kimse için bir sır olmasa gerek? Eğer bilgisayar isimleri de tanımlanabilir bir kodlama ile oluşturulmamışsa, ortamda bir Domain yoksa hangi işlemi hangi kullanıcı gerçekleştirmiş bulmak neredeyse imkansız oluyor. Özellikle kritik işlemlerin kimler tarafından, nasıl gerçekleştirildiğinin izini bulabilmek için tüm işlemleri birbirinden ayırt edebilmeniz gerekiyor. Bunun için de her gerçek kullanıcının hesap bilgilerini sadece kendisinin bildiği eşsiz kullanıcıları olması gerekiyor. Veritabanına erişimi olacak tüm şirket çalışanlarına kendi kullanıcısının mesuliyetinin kendisine ait olduğu net olarak anlatılmalı ve bu madde ilgili yaptırım ifadeleriyle işe giriş sözleşmesine de eklenmeli.
7- Sadece gerektiği kadar yetki:
Ne denirse densin, bazı ortamlarda çeşitli sebeplerle 1. maddede bahsini ettiğim ortamlar ayrılığı gerçekleştirilmiyor. Durum her ne olursa olsun örneğin bir yazılımcının yeni veritabanı oluşturmaya, varolan veritabanını veya tabloları silmeye ne sıklıkta ihtiyacı olur? Neredeyse senede 1-2 kere. Bir yazılımcının temel ihtiyaçları SP/Function/Trigger/Table gibi nesneleri oluşturmak ve değiştirmektir, ayrıca Select ve DML yetkisine ihtiyaç duyar; yani temel olarak ihtiyaçları aslında veritabanı seviyesindedir, sunucu seviyesinde değil. Gereğinden fazla gücünüz olması durumunda, hata yapma şansınız da artmış olur. Misal son model bir Ferrari ile mi hız kazası yapmanız daha olasıdır, yoksa 1.0 motorlu bir Kia Picanto ile mi? Eğer çalışanın ihtiyacı Kia Picanto ise, ona Ferrari vermeyin, ki kaza yapabilemesin.
Özellikle yeni çalışmaya başladığımız şirketlerde yetki kısıtlaması çalışması yaparken bazı arkadaşlar tarafından ilk önce ciddi tepkilerle karşılaşabiliyoruz, fakat daha sonra gerçekten ne yapmaya çalıştığımızı fark ettiklerinde onlar da çok memnun oluyorlar. Araç sürerken emniyet kemerinin takılması gerektiği gibi, maksat hem veriyi korumak, hem de çalışanı.
8-Hassas verilerinizi maskeleyin:
Gerek gerçek kişilerin kimliklerini ifşa edebilecek, gerekse şirket için hassas olan verileri doğrudan veritabanı seviyesinde maskeleyin. Bunu SQL Server 2016 ile birlikte gelen Dynamic Data Masking özelliği ile gerçekleştirebilirsiniz. SQL Server'ın Standard Edition'ında bile var bu özellik. Hiç bir kesinti veya uygulama tarafında kod değişikliği gerektirmeyen bir işlem bu. Sadece öncesinde ilgili yöneticiler ve çalışanlarla birkaç toplantı düzenleyip, hassas verileri tanımlayıp, belirleyip, tüm çalışanları bilgilendirip, öyle aksiyon almak gerekiyor.
9-Verilerinizi yedekleyin, fakat yedeklerken güvenliği ihmal etmeyin:
Mümkünse veritabanlarınızı şifreleyerek yedekleyin. Örneğin bunun için Transparent Data Encryption da kullanabilirsiniz. Böylece kötü niyetli kişiler bir şekilde yedek dosyalarınıza erişse bile, elde ettikleri veritabanlarını açamazlar.
Ayrıca Disaster Recovery (DR) Site'ınızda da benzer güvenlik önlemlerini aldığınızdan emin olun. Örneğin bir keresinde bir müşterimin canlı ortamına erişemeyen saldırganların DR ortamına saldırdıklarını fark etmiş ve ilgili kişilere bilgi verip açıkları kapattırmıştım.
10-Veritabanı sunucunuza art arda yapılan hatalı giriş denemelerini denetleyin ve bu denemelerden haberdar olun:
Eğer veritabanı sunucunuza art arda erişilmeye çalışılıyorsa ve bol bol hata alınıyorsa ya bir veritabanınız herhangi bir sebeple erişilemez duruma gelmiştir, ya bir kullanıcınızın hesabı bloke olmuştur ya da sunucunuza içeriden veya dışarıdan "brute force" yöntemiyle erişilmeye çalışılıyordur.
Ben bu kontrolü yaparak son 2 sene içerisinde en az 3-4 kere kötü niyetli saldırı girişimini fark ettim ve bu sayede gerekli önlemleri alarak ilgili sunucuların açıklarını kapatabildik.
11- Veritabanı sunucunuza yapılan başarılı girişleri denetleyin:
Sadece başarısız giriş denemelerini değil, başarılı girişleri de kontrol etmemiz gerekiyor, ki eğer bir çalışanın veya uygulama/vekil kullanıcının bilgileri kötü niyetli birisinin eline geçerse ve veritabanına bağlanırsa haberimiz olsun. Aksi durumda bağlantı kurulan veritabanı sunucusundaki erişim sağlanan tüm veriler peyderpey çalınır ve ruhunuz duymaz.
Bu kontrol için örneğin Microsoft Azure'da Advanced Threat Detection diye bir yöntem var, fakat on-prem sunucular için henüz benzer bir teknik sunmuyor bize Microsoft. Microsoft'un Güvenlik Zirvesi'nde Advanced Threat Detection ile ilk karşılaştığımda on-prem'e bunu nasıl uyarlarım diye düşündüm. İlk aklıma gelen prototip verimli çalışmıyordu, fakat o prototipin son versiyonu şu anda tüm müşterilerimin ortamlarında çok verimli bir şekilde çalışıyor. Aşağıda bir örnek paylaşıyorum:
12-Özellikle hassas verilerinizdeki değişiklikleri kayıt altına alın:
Eğer bu işe ayırabilecek ciddi bir bütçeniz varsa zaten bir güvenlik ekibiniz de vardır ve IBM Guardium veya Imperva gibi milyon dolarlık seçeneklere bakıyorsunuzdur. Fakat bütçeniz nispeten dar ise SQL Server 2016 Service Pack 1 ile artık Standard Edition'da bile kullanılabilen SQL Server Database Auditing özelliğinden faydalanabilirsiniz. Database Auditing'i tek başına kullandığınızda raporlama açısından ciddi zorluklar yaşarsınız, hiç pratik değildir ve log yönetimi çok çok sıkıntılıdır; fakat Database Auditing'i oldukça uygun bir lisans maliyeti olan CryptoLog gibi bir uygulama ile birleştirdiğinizde çok daha verimli bir sonuç elde edersiniz.
13- Toplu veri sorgulamalarından ve değişikliklerinden haberdar olun:
Kullanıcılarınız veritabanı sunucunuzdaki verileri toplu bir şekilde sorguladığında veya toplu bir değişiklik (Update/Delete gibi) yaptığında bundan haberdar olmak istemek için birden fazla nedeniniz var. Tabii ki öncelikli nedenini güvenlik. Özellikle finansal verilerde yapılacak toplu bir değişiklik çok can yakabilir veya kötü niyetli biri verilerinizi şifreleyip fidye isteyebilir*.
* Bu gibi senaryoların geri dönüş seçenekleri mevcut, fakat uzun bir konu.
Toplu sorgulamalardan da haberdar olmak istersiniz, çünkü mesela müşteri verilerinizin toplu bir şekilde şirket dışarısına çıkarılmasını istemezsiniz. Evet, olan olmuştur; fakat ne kadar kısa sürede ayrıntılardan haberdar olursanız, o kadar kısa sürede aksiyon alabilirsiniz.
14- Eğer zorunda değilseniz SQL Authentication değil, Windows Authentication kullanın:
Microsoft'a göre SQL Authentication uzun süredir "Deprecated" bir özellik, yani bir süre sonra kaldırılacak; fakat bu durum uzun yıllardır böyle ve ben yakın zamanda da kaldırılacağını düşünmüyorum. Microsoft'un bu özelliği kaldırmak istemesinin nedeni de güvenlik. Fikir de şu, zaten bir Domain/Local hesabımız var, veritabanına bağlanırken de bunu kullanalım. Ayrı ayrı kullanıcıların ve şifrelerin olması, insanların kullanıcı hesaplarının ayrıntılarını kolay ulaşılabilecek şekilde sağa sola not etmesine neden oluyor. Haliyle bu da ciddi bir güvenlik açığına neden oluyor.
Tabii SQL Authentication ihtiyacı birçok senaryo için hala bir gerçek, fakat olabildiğince bilinçli olmakta ve Windows Authentication kullanmakta fayda var.
15-Yerel Güvenlik Politikası'nı kullanın:
Hem yeni Login'ler oluştururken, hem de varolan Login'leriniz için Windows işletim seviyesindeki Yerel Güvenlik Politikalarından faydalanın. Bu sayede kullanıcılarınızın Login şifrelerinin belli bir uzunlukta ve zorlukta belirlenmesini sağlayabilir, kullanıcılarınıza belli süreler içerisinde şifrelerini değiştirmesini zorlayabilirsiniz.
Not: Şifrelerin sıklıkla değiştirilmesinin de kendi başına bir güvenlik açığına neden olduğuna dair bazı görüşler var, şahsen ben de bu görüşlerin kısmen de olsa doğruluk payı olduğunu düşünüyorum. Örneğin 30 günde bir şifre değiştirmek zorunda kalan sıradan bir kullanıcının her 30 günde bir değişen bu karışık şifreyi nerede tutması bekleniyor? Aklında tutamayacağı aşikar. Ya telefonuna not ediyor, ya da bilgisayarının masaüstünde duran bir metin dosyasına. Yani güvenlikte aşırıya kaçıp, güvenlik önleminin bir başka güvenlik açığına dönüşmemesini sağlamak gerekiyor.
16-Rutin Login şifre testleri uygulayın:
Özellikle herhangi bir nedenle Windows Yerel Güvenlik Politikasının uygulanmadığı kullanıcılar için bu denetimin yapılmasında fayda var. Bu denetim sayesinde birçok ortamda örneğin şifresi 111111 olan kullanıcı tespit ettim.
17-Veritabanı ve uygulama sunucularına RDP yetkisi:
Sadece sistem yöneticilerinin ve veritabanı yöneticilerinin veritabanı sunucusuna RDP yetkisi olabilir, o kadar. Bu yetki de rutin olarak değil, sadece gerektiğinde kullanılmalıdır. Veritabanı yönetiminin rutin olarak veritabanı sunucusuna RDP yaparak uygulanması iyi bir pratik değildir, çünkü çalıştırdığımız uygulamalar çeşitli nedenlerle "crash" olabilir, hiç beklemediğimiz şekilde yüksek CPU ve RAM tüketebilir, bunlar da işletim sisteminin kararsız çalışmasına neden olabilir ve böyle bir şeyin olmasını istemeyiz.
RDP yetkisinin sınırlandırılmasının bir başka amacı ise veritabanı dosyalarının kopyalama yöntemiyle şirket dışına çıkarılamaması ve kopyalanamamasının sağlanmasıdır.
18-Güvenlik konusunda bilinç:
Sonuç itibariyle en zayıf halkanız kadar güçlüsünüzdür. Şirket çalışanlarının veritabanı yöneticisinden çaycısına, yazılım mühendisinden şirket girişindeki danışmanlığa kadar bilinçli olması gerekiyor, ki mesela şirketin bahçesinde bulunan bir USB bellek ağdaki bir bilgisayara takılmasın, şifreler paylaşılmasın, yetkisiz kişiler yetkili olmadıkları departmanlara fiziksel olarak giremesin.
Eğer Microsoft SQL Server veritabanı sunucularınızın yeni versiyonlara yükseltilmesi ve güvenlik gibi konularda desteğe ihtiyacınız olursa bana ulaşabilirsiniz.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Yönettiğim ortamların birinde disk altyapısı (storage) kaynaklı ciddi bir sorun oluştu. Şöyle bir senaryo düşünün ki, X veri merkezinde barındırdığımız canlı veritabanı ve uygulama sunucularımıza ait dosyaların ve yedeklerimizin bulunduğu disk altyapısı Y firmasının ürünü olan Storage'taki bir yazılım sorunu (bug) nedeniyle komple bozuluyor (corruption). Ne canlı ortam verilerine, ne de yedeklerine ulaşılamıyor. Tam bir kriz!
Bir süre sonra veri merkezi 1 gün öncesine ait veritabanı yedeklerine ulaşabildiğini söyledi, fakat bu bizim için 1 günlük veri kaybı demekti. Bu kritik bir sistem olduğu için tabii ki Transaction Log yedekleri alıyorduk ve bu yedek dosyaları da sistemi tamamen kaybetmeden 1 saat öncesine kadar geri getirilebildi. Bu noktada veri kaybı 1 saatti. Yine neyse ki bu ortamın BT yöneticisi felaket senaryolarının bilincindeydi ve bu konuda yatırım yapılmasını sağlamıştı, bu sayede başka bir veri merkezinde bulunan yedeklerimizi kullanarak yalnızca 1 dakikalık veri kaybı ile bu kriz atlatılmış oldu.
Not: Müşteri felaket önleme seçenekleri konusunda bilgilendirilmişti. Maliyet-fayda hesabına göre 1 dakikalık veri kaybı müşteri için kabul edilebilirdi.
Sadece son 2 senede 4 kere buna benzer durum için yedekliliğin önemine dair yazılar yazmışım (yazı1, yazı2, yazı3, yazı4), en azından bir çırpıda bulabildiklerim bunlar. Disk altyapıları kısmen veya tamamen yazılım (firmware) veya donanım hatası nedeniyle bozulabilir. Ayrıca verileriniz disk veya sistem yöneticileri tarafından yanlışlıkla silinebilir veya bir saldırı neticesinde bozulabilir. Sistemleriniz çeşitli nedenlerle kullanılamaz, ulaşılamaz duruma gelebilir. Bu gibi olasılıklar sizin başınıza gelmeyecek sanmayın, çok yanılırsınız. Türkiye'nin veya dünyanın en büyük kurumlarının bile başlarına geliyor bu durumlar. Şahsen yönettiğim ortamlarda ister istemez, şartlar ve imkanlar dahilindeki her türlü önleme rağmen bahsettiğim çeşitli nedenlerle senede ortalama 2 kere yaşıyorum benzer senaryoları. Şimdiye kadar bunu tatmadıysanız bile, üzgünüm ama emin olun eninde sonunda tadacaksınız. En iyisi, o güne şimdiden hazırlıklı olmak!
Size tavsiyem şirketiniz içerisindeki ilgili partilerle bir toplantı yapın ve şu soruların cevaplarını arayın:
"Ne kadar sürelik veri kaybına tahammülümüz var? 1 gün? 1 saat? 1 dakika? Birkaç saniye?"
"Sistemimizin en fazla ne kadar süre kapalı kalmasını tolere edebiliriz?"
Tabii ki iki soruya da ilk etapta "Sıfır!" yanıtının gelmesi şaşırtıcı olmayacak, fakat bunun maliyet-fayda hesabının yapılması gerekiyor. Çünkü kullandığınız SQL Server Edition'ına göre farklı lisans ücretleri ödüyorsunuz ve yine Edition'lara göre farklı sürekli kullanılabilirlik ve felaket önleme seçenekleri mevcut. İhtiyacınıza en uygun çözümü örneğin SQL Server'ın Standard Edition'ıyla da üretebilirsiniz, böylece lisans maliyetlerinizi hele ki dövizin bu seviyelerde olduğu bu zamanlarda ciddi oranda düşürebilirsiniz. Ayrıca şunu da belirtmek gerekir ki bütçe musluklarını açsanız bile çeşitli nedenlerle tamamen kesintisiz bir ortam kuramazsınız, fakat kesintinin olabildiğince kısa sürmesini ve doğru yönetilmesini sağlayabilirsiniz.
Veri kayıpsız, az kesintili günler dilerim.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Ortamlardan birinden 2-3 gündür aşağıda da paylaştığım anormal bir hata mesajı geliyordu. Açıkçası gelen hata mesajını, hatayı gönderen kaynak nedeniyle pek de önemli saymamış ve iş listemin ön sıralarına koymamıştım.
 |
Oluşan hata alarmı |
Hata "syspolicy_purge_history" isimli SQL Server'ın SQL Server Agent Job tarihçesini silen Job'tan geliyordu. Bu standart, SQL Server kurulumuyla gelen bir Job'tır. Kısa süreli çalışmayışı kritik bir sorun yaratmaz, ama uzun süre çalışmazsa canınızı sıkabilecek sonuçlar doğurabilir. Sorunu inceleyince hatanın alındığı adımın Job'ın Powershell komutu içeren 3. adımı olduğunu gördüm. Önceden karşılaşmadığım bir hata idi, biraz derinine inmek istedim ve indikçe durum daha da ilginç bir hal alıyordu. Derken tamamen şansa işletim sistemi diski olan C: diskinin kök dizinindeki bazı "klasörlerin" uzantılarının *.exe olduğu çekti dikkatimi ve haliyle dehşete kapıldım!
 |
Temsili ekran görüntüsü |
Böyle bir manzarayı görmeyeli en az 10-15 sene olmuştur... Çok şaşırdım. Canlı bir veritabanı sunucusunun işletim sistemi diski (C:) bu!
Hemen ilgili yöneticilere ve mühendis arkadaşlara haber verdim ve hep beraber durumu incelemeye başladık. Bir süre sonra kötü niyetli bir korsanın iç ağa dışarıdan giriş yaptığı, bunu da Domain Admin grubuna üye olan bir hesabın bilgilerini ele geçirerek yaptığı anlaşıldı. Hesap Domain Admin yetkisine sahip olduğu için kötü niyetli kişi ağda istediği gibi gezinmiş, antivirüs uygulamasını kapatmış ve kim bilir daha neler yapmış... Yaptığı birçok şey çeşitli mekanizmalarla kayıt altına alınmış; fakat hesap zaten varolan ve varolması beklenen bir hesap olduğu için hareketleri göze batmamış. Hesabın bilgilerini elde eden kötü niyetli kişinin ağda hemen veritabanı sunucularına yöneldiği anlaşılıyor. Birkaç kere veritabanına bağlanmayı denemiş, fakat izlediğimiz Best Practice'ler sayesinde veritabanlarına bağlanamamış. Eğer veritabanı sunucumuzda, birçok ortamda gördüğüm gibi Domain Admin'ler ve Local Administrator'lar için yetki tanımlı olsaydı bu ortamda ne durumda olurduk düşünmek bile istemiyorum.
Şu anda neyse ki her şey kontrol altında.
Peki bu atak vakitlice fark edilmeseydi ve müdahale edilmeseydi neler olabilirdi? Aklıma gelen birkaç olasılık şöyle:
- Sisteme giren kötü niyetli kişi tüm veritabanlarını ve uygulama kodlarını ele geçirebilirdi,
- Varolan sunuculardaki dosyalar son zamanlarda popüler olan bir saldırı yöntemiyle şifrelenebilir ve fidye istenebilirdi,
- Eğer veritabanına bağlanabilseydi ve yeterince dersine çalışmış olsaydı finansal verilerle oynayabilir ve kazanç elde etmeye çalışabilirdi,
- Sadece yıkıcı bir etkiye neden olmak için verileri sonra fark edeceğimiz şekilde kirletebilirdi, ki yedeklerden geri dönebilmek için çok geç olurdu veya yedekleri de silebilirdi.
Bu hikayeden veritabanı yönetimi ve güvenliği açısından çıkarılması gereken dersler:
- Sadece gereken kişilere, gerektiği kadar yetki verme prensibinden asla şaşmayın. Mümkünse yetkileri geçici olarak verin ve sadece gerektiği sürelerde verin. Eğer geliştirme ve canlı öncesi/kalite testi ortamlarınız varsa canlı veritabanı sunucularınızda kimseye yetki vermeyin,
- Gerekli yetkilendirmeleri yaptıktan sonra eğer varsa "sa" hesabını ya Disabled duruma getirin, ya da adını değiştirin, çünkü tüm korsanlar bu hesabın varlığından haberdardır,
- SQL Server'ı Default Instance olarak kurduğunuzda Database Engine servisi 1433 portunu kullanır ve tüm korsanlar bunu bilir, bu nedenle farklı bir port numarası kullanın,
- Veritabanınıza yapılan hatalı giriş denemelerini takip edin, ortamınızın çalışma doğası dışında belli bir eşik değer geçildiğinde alarm üretilmesini sağlayın,
- Bu senaryoda olduğu gibi normal şartlarda oluşmayan hataların başka sorunların göstergesi olabileceğini unutmayın,
- * Yedeklerinizi mümkünse şifreli (encrypted) saklayın, ki yedek dosyaları kötü niyetli kişilerce ele geçirilse dahi içeriğe ulaşamasınlar,
- * Mümkünse Transparent Data Encryption (TDE) özelliğinden faydalanın, ki doğrudan veritabanı dosyalarınız ele geçirilse bile veriler ele geçirilemesin,
- SQL Server ve işletim sistemi güvenlik güncellemelerini uygulamayı ihmal etmeyin.
* Şifreleme için kullandığınız sertifikaları veritabanı yedek dosyalarının olduğu yerden çok farklı bir konumda saklayın, ki korsan bu anahtara ulaşamasın ki şifreleme önleminiz işe yarasın.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Bundan önceki yazımı yazalı 2 ay olmuş. Efendim son 2 aydır çok hummalı bir şekilde ve uzun zamandır aklımda olan bir projeye başlama kararı aldım ve gün itibariyle oldukça şekillendi, sonuçtan da oldukça memnunum. Bu heyecanımı sizlerle de paylaşmak istedim.
Not: Baştan belirtmek isterim ki yazı ister istemez biraz pazarlama kokacak, çünkü ürettiğim ürün doğrudan verdiğim hizmet ile ilgili, yani herkese ücretsiz olarak açık bir ürün değil.
Bakım ve Destek Anlaşması kapsamında müşterilerime yıllardır geliştiriyor ve güncelliyor olduğum Kangal isimli veritabanı izleme mekanizmamı kuruyorum. Çok özetle bu mekanizma ile müşterilerimin veritabanı sunucuları güvenlik, performans, yönetim, bakım ve hata izleme gibi birçok kategoride sürekli denetleniyor ve bir sorun anında hemen alarm üretiliyor ve ilgili kişiler ayrıntılı bir şekilde bilgilendiriliyor.
Bu sene Kangal için farklı talepler gelmeye başladı. Örneğin İzmir'de bulunan büyük bir yazılım firması ile geleneksel bakım ve destek anlaşması yapmak yerine, Kangal'ın kiralanması ve yanında danışmanlık hizmeti verilmesi üzerine anlaştık. Bir banka ile de Kangal'ın kiralanması üzerine görüştük. Fakat o zaman Kangal'ın bir arayüz uygulaması yoktu. Denetim ve izlemeyi yapan kodların her ne kadar yönetimi kolay olsa da, bu hiçbir zaman şık ve kullanışlı bir arayüzün yerini tutmaz. Ayrıca biriken istatistiklerin grafik arayüzlerle yorumlanması çok daha anlaşılır olabiliyor.
Bunun yanısıra Bakım ve Destek Anlaşmamız olan firmalardaki BT yöneticilerine Kangal'ın marifetlerini daha iyi gösterebilmem gerektiğini fark ettim. Yöneticiler bir hizmet alıyordu, alarmları görüyorlar, sorunlara da en kısa sürede müdahale edildiğini biliyorlardı; fakat bir taraftan da kendileri de bir şeyleri kurcalamak isteyebiliyorlardı.
Ben de bu yeni duruma ve talebe uyum sağlamak için Çoban'ı geliştirdim. Bu haberin özetini sizlerle burada birkaç görsel eşliğinde paylaşmak istedim. Yazı çok uzun ve sıkıcı olmasın diye sadece birkaç ekrana dair bilgi paylaşacağım.
 |
Çoban ile Kangal ilişkisi |
Öncelikle şu temel bilgileri paylaşmak isterim:
- Verileri toplayan, raporları ve e-posta alarmlarını üreten Kangal'dır. Her bir veritabanı sunucusunda bir tane olur. Verileriniz kesinlikle dışarıya çıkmaz ve uzaktanki bir sunucuda depolanmaz. Kendi veritabanı sunucunuz üstünde tutulur. Kangal'ı bir "Agent" gibi düşünebilirsiniz.
- Çoban, Kangal'larda biriken verilerin analiz edilmesini, görsellerle daha iyi yorumlanabilmesini ve Kangal'ların kolaylıkla yapılandırılmasını sağlar. Örneğin Çoban'ı kendi ve diğer iş arkadaşlarınızın bilgisayarına kurarsınız ve tüm Kangal'ları yönetirsiniz. Çoban bir yönetim ve analiz arayüzüdür.
- İki ürünün hem entegre, hem de ayrı olmasının nedeni esneklik sağlamak. Örneğin Çoban'a gerek kalmadan Kangal tek başına çalışabilir.
- Lisanslama Kangal bazında yapılır.
 |
Çoban'ın giriş sayfası. |
Her olasılığa karşın uygulamayı tamamen İngilizce dilinde tasarladım. Şu anda hala Beta sürümleri yayınlanıyor. Bununla birlikte ilk versiyonundan beri pilot müşterilerim tarafından kullanılıyor.
Sağolsunlar, birçok firmaya girip çıkma, birçok BT ve veritabanı yöneticisiyle tanışma ve ihtiyaçlarını dinleme şansım oluyor, ayrıca ben kendim de 12 senedir veritabanı yöneticisi olarak çalışıyorum ve 21 senedir kod yazıyorum. Kangal'ı tasarlarken amacım topladığı veriyi bulunduğu ortamdan çıkartmadan (güvenli) dağıtık planda çalışabilecek (esnek) bir yapı kurmaktı. Çoban ile de bu biriken veriden hem BT yöneticilerinin faydalanabilmesini istedim, hem de veritabanı yöneticilerinin hayatlarını kolaylaştırmak istedim.
 |
Instance seviyesindeki iyi/kötü pratik kontrolü ve durum raporu |
Çoban ile bir SQL Server Instance'ına bağlanır bağlanmaz, o Instance ile ilgili sunucu düzeyindeki olası kötü pratikleri veya olası sorun noktalarını görürsünüz. Çoban size en sık karşılaşılan sorunları işaret eder.
 |
İşlemci kullanım ayrıntıları |
Ana panodaki işlemci ile ilgili sayfada tek bakışta son 30 dakika (veya seçeceğiniz farklı bir zaman dilimi) içerisinde kullanılan işlemci miktarını, ayrıca aynı zaman diliminin dünkü ve hatta geçen haftaki işlemci kullanım miktarını bir seferde görebilirsiniz. Böylece yaşanan yoğunluk normal mi, işlemci kullanımı dün veya geçen hafta da böyle miydi sorusunun cevabına hemen ulaşabilirsiniz. Ayrıca yine aynı ekranda işlemci kaynaklarının en çok hangi veritabanındaki kodlar tarafından tüketildiğini de görebilirsiniz. Önümüzdeki versiyonlarda da bu ekrana en fazla işlemci kaynağı tüketen sorguların ekleneceğini tahmin etmek zor değil sanırım.
 |
Ayarlar |
Kolay anlaşılabilir ve pratik olsun diye ayarlar ekranını yukarıdaki gibi, cümlelerle tasarladım. Çoban'dan yapacağınız tüm değişiklikler, doğrudan bağlandığınız sunucudaki Kangal'da uygulanacaktır.
 |
Uygulama hatalarını takip ekranı |
Uygulamalarınızın veritabanında ne zaman, hangi SQL komutunu çalıştırarak, ne hata aldığını bu ekrandan geriye dönük olarak takip edebilirsiniz. Bu tür verileri kaç güne kadar geriye dönük tutabileceğinizi Çoban'ın ayarlar ekranından belirleyebilirsiniz. Bu ayarlara göre Kangal, eski istatistikleri otomatik olarak silecektir.
 |
Özellikler ekranı |
Şu anda 79 tane özellik var. Yukarıdaki ekran görüntüsünden de görebileceğiniz üzere bu özellikler Açık kalan Transaction, Blocking, kullanılabilir disk alanı, işlemci kontrolü gibi özellikler. Dilediğiniz özelliği, dilediğiniz sunucuda açıp kapatabilirsiniz. Hatta dilerseniz istediğiniz özelliği, istediğiniz zaman aralığında uyku durumuna sokabilirsiniz, böylece istediğiniz zaman aralıklarında alarm üretilmemiş olur. Yine istediğiniz alarmı, istediğiniz kişi veya gruba yönlendirebilirsiniz. Ayarlar penceresinde posta grupları oluşturabiliyorsunuz, o grupları bu ekrandaki istediğiniz özelliğe atayabilirsiniz.
Yine Özellikler'le doğrudan bağlantılı olarak, aşağıdaki ekran görüntüsünü paylaştığım İstisnalar sayfasında istediğiniz özellik için istisna tanımlayabiliyorsunuz. Örneğin istisna tanımlayarak X veritabanında Blocking oluştuğunda veya Y uygulamasından çalıştırılan ve uzun süren sorgular için alarm üretilmemesini sağlayabilirsiniz.
 |
İstisna tanım ekranı |
Yukarıdaki özellikler sayesinde aşağıdaki başlıklarla ve sorunlar hakkında ayrıntılı bilgiler içeren e-postalar alıyorsunuz.
 |
Sistem olay kayıtları |
Kangal için de, Çoban için de bakım ve destek anlaşmamız devam ettiği sürece ek bir ücret ödemeden faydalanabiliyorsunuz. İki ürün için de sık sık ve ayrı ayrı güncelleme üretilmeye, yeni özellikler eklenmeye devam edecek. Güncellemeleri de yine Çoban'ın ilgili arayüzleri vasıtasıyla kolaylıkla yapabileceksiniz. Bunun için size özel oluşturulan bir kullanıcı hesabını kullanıyorsunuz.
 |
Kangal ve Çoban güncellemeleri |
Aşağıda paylaştığım DDL Change Tracking desteğini Çoban'a 1.0.0.5 versiyonunda ekledim. Bu özelliği hangi veritabanında etkinleştirirseniz o veritabanındaki tüm tablo, prosedür, kullanıcı ve benzer değişiklikler aşağıdaki gibi kayıt altına alınır. Eğer dilerseniz kritik nesneler için tanım oluşturabilirsiniz ve o nesnelerde değişiklik gerçekleştiğinde (örneğin kritik bir tabloya yeni bir alan eklendiğinde) alarm üretilir.
 |
DDL Change Tracking |
Aşağıdaki 2 ekranda da Log Shipping ve Replication takibine dair ayrıntıları görebilirsiniz.
 |
Log Shipping |
 |
Replication |
Şikayetlerinizi, alacağınız olası hataları ve taleplerinizi aşağıdaki form vasıtasıyla doğrudan bana ulaştırabiliyorsunuz. Kaynak kodlar bizde, talebinize ve ihtiyacınıza özel yeni özellikler ekleyebilir, varolanları güncelleyebiliriz.
 |
Geribildirim formu |
Tüm iş ortaklarım için faydalı olması dileğiyle.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Geçen hafta çok ilginç bir Always On Availability Groups (AG) sorunu ile karşılaştım, bunu yazmazsam olmazdı.
Önce ortam hakkında özet bilgi vereyim. Bu ortamda SQL Server 2014 + Service Pack 2 kurulu ve 2 Replica'dan oluşan bir Always On AG yapısı var; geçen senenin sonlarına doğru kurmuştuk. Müşteri, 2. Replica'yı sürekli kullanılabilirlik için değil, sadece raporlama için istemişti, bu nedenle Always On AG temel amacından birazcık saparak sürekli kullanılabilirlik için kullanılmıyor.
Sorun yaşandığı anda ben de başka bir şeyle meşguldüm, kesintiye dair telefon geldi ve ilk müdahaleyi telefonda yaptık. Fakat temel şeyler sonuç vermeyince kısa bir süre sonra sisteme ben bağlandım ve kontrollere başladım.
Canlı sunucuya bağlandığımda SQL Server Database Engine servisi çalışıyordu, fakat Always On AG Resource Group Offline durumdaydı. Cluster Resource'u bir türlü Online duruma gelmiyordu ve çok ilginç bir şekilde SQL Server Error Log'ta, Windows System Event Log'larında ve Cluster Log'larında aradığım ayrıntıları bulamadım. Bir taraftan da kesinti devam ediyordu, tüm Login'ler veritabanlarına erişemediğine dair hata alıyordu. En temel genel Microsoft sorun çözücü yöntem olarak sunucuyu yeniden başlattım. Çok ilginç bir şekilde sorunu bu hamle de çözmemişti (tabii ki takılıyorum)...
SQL Server Database Engine'e bağlanıp veritabanlarını kontrol edeyim dedim...

ve yukarıdaki ekranla karşılaşınca açıkçası çok şaşırdım, çünkü yazımın girişinde belirttiğim gibi bu ortamda Always On AG vardı ve bu da tek Primary Replica olabilecek makineydi, nasıl veritabanları "Restoring" durumda olabilirdi ki? Secondary Replica'daki veritabanları da "Not synchronizing" durumdaydı.
Henüz bunun şaşkınlığını atlatamadan bir de ne göreyim:
Yukarıdaki ekran görüntüsü Primary Replica'ya ait. Always On AG yapılandırmam yok olmuş!
Bunun nasıl olabileceği konusunda en ufak bir fikrim yok. Yani ne, nasıl tetiklenir de Always On AG yapısını bu şekilde siler hiç bilemedim. Secondary Replica'yı kontrol etmek geldi aklıma, bağlandım baktım, orada duruyor yapılandırma. Bulguları birleştirince Always On AG Cluster Resource'unun da neden bir türlü Online olmadığı anlaşıldı.
Sahadaki servis kesintisi sorununu gidermek için "RESTORE DATABASE" komutuyla hemen veritabanlarını Online duruma getirdim* ve servislerin ayağa kalktığını teyit ettim. Artık sahada kesinti yoktu. Bundan sonraki aşama Always On AG'yi ayağa kaldırmaktı.
* Dikkatinizi çekerim veritabanları Restoring durumdaydı, öyle veya böyle bu duruma gelmişti, veritabanlarına ulaşmaya çalışan Login'ler de bu nedenle hata alıyordu ve Database Engine servisinin açılışında da herhangi bir sorun yoktu, bu nedenle basit bir RESTORE DATABASE ile veritabanlarını açabilir ve sahadaki kesintiyi engelleyebilirdim, temel öncelik her zaman kesintiyi güvenli bir şekilde sona erdirmektir.
Primary Replica'daki Database Engine servisinin Always On AG için Enabled durumunda olup olmadığını teyit ederek başladım işe. Daha sonra veritabanları açıldıktan sonra Primary Replica'da herhangi bir Transaction Log dosyası yedeği alınmış mı diye kontrol ettim. Eğer alınan bir yedek varsa bu yedekler Secondary Replica ile senkronizasyonun sağlanabilmesi için Secondary Replica'daki veritabanlarına da uygulanmalıydı. Komple yeniden kuruluma gerek yoktu, çünkü Secondary Replica'daki veritabanları duruyordu, sadece iki Replica'daki veritabanları arasında herhangi bir Log Sequence Number (LSN) boşluğu olmadığından emin olmak yeterliydi, eğer boşluk varsa da bu eksikler Transaction Log yedekleri Secondary Replica'da Restore edilerek giderilebilirdi.
İki Replica'daki veritabanlarının arasında LSN boşluğu olmadığından da emin olduktan sonra Always On AG'yi ilgili veritabanlarıyla tekrar oluşturdum ve tüm eksiklikler giderilmiş oldu. Artık sistem kesinti olmadan önceki gibi çalışıyordu.
Tabii bu noktadan sonra sorunun nedenini araştırmak gerekiyordu. Ne olmuştu da kesinti oluşmuştu?
Always On AG, diğer birçok Microsoft teknolojisi gibi kurulumu nispeten kolaydır, bu nedenle birçok şirkette şık arayüzler kullanılarak "ileri, ileri" denilerek kurulur; fakat birçok senaryoda ya doğru tasarlanmaz, ya doğru yönetilmez, ya da sistem işlerliği doğru takip edilmez. Bazen de bizim senaryomuzda olduğu gibi ne yaparsanız yapın, birileri bir şekilde bir şeyleri bozabilir. Bizim senaryomuzda birisi bir sorgu çalıştırmış ve sunucu bu aşırı garip sorgu nedeniyle birkaç dakika cevap veremez duruma gelmiş. Bu nedenle Cluster, SQL Server'dan cevap alamamış ve "lease" yenilenememiş ve Cluster tarafından bu sunucu sağlıksız sayılıp servis kapatılmış. (Ödev: Böyle senaryolar için de bu garip sorguları çalıştırabilecek Login'ler tespit edilip Resource Governor'ın kullanımı düşünülmelidir, bu sayede bu potansiyel tehlikeli kullanıcıların işlemci kaynağını azami kullanım miktarı sınırlanabilir, bu aşamada müşteri ile bunu görüşüyoruz.)
Yeri gelmişken tekrar vurgulamak istedim. Always On AG, Log Shipping, Replication, Database Mirroring veya Failover Clustered Instance'larınızı sadece kurup kendi hallerine bırakmayın. Yakından izleyin. Aktarımlar geride kaldığında, yapının parçalarından birinde kesinti olduğunda, uygulamalar Virtual Network Name / Listener gibi sunucu agnostik elemanlar yerine doğrudan üye sunuculara bağlandığında haberiniz olsun istersiniz. Daha sürdürülebilir, daha sağlıklı ve daha kesintisiz ortamlar için bunlar sadece en temel kontrollerden birkaçıdır.
Yazıyı yazarken eşim de o anda bir fotoğraf çekmiş, bu yazıyı sevgili Tuncel Kurtiz'in Zeytinbağı'ndayken yazmıştım, nur içinde yatsın.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Birkaç hafta önce bir müşterim gece 23:00 sularında aradı ve çok kritik bir Microsoft SQL Server ortamındaki yine çok kritik bir tabloda aşağıdaki gibi bir hata aldıklarını söyledi:
Arithmetic overflow error converting IDENTITY to data type int.
Açıklama: Eğer bu hatayı alıyorsanız, veri tipi Integer olan ve Identity özelliği olan bir tabloya yeni bir kayıt ekleyemiyorsunuz demektir. Integer veri tipinin tutabileceği veri aralığı -2.147.483.648'den 2.147.483.647'ye kadardır.
Not: Benzer bir hatayı Smallint veya Bigint veri tipiyle tanımlanmış alanlar için de alabilirsiniz, tabii ki bu durumda hata mesajının sonundaki veri tipi değişkenlik gösterecektir.
İlgili tablo kesintiyi tolere edemeyecek bir tabloydu, her ne kadar yeni kayıt alamasa da, varolan kayıtlarla da sistem çalışabiliyordu. Yani esas kesinti yeni kayıt girilememesinden değil, varolan kayıtlara ulaşılamamasından kaynaklanıyordu ve bu hata varolan kayıtlara ulaşılamamasına neden olmuyordu. Fakat bu tabloya yeni kayıt ekleme ihtiyacı da kaçınılmazdı, yani sorun muhakkak çözülmeliydi.
Müşterimin ilk aklına gelen şey veri tipini BIGINT'e çevirmekti, fakat şartları düşündüğümüzde bu kötü bir seçenekti çünkü hem Identity alanı Primary Key ve Clustered indeks idi, hem de bu değişiklik uygulama kodlarını da etkilediği için kodlarda da değişiklik yapılması gerekiyordu. Bu hem kesinti gerektirecek bir işlemdi, hem de çok temel bir tablo olduğu için uygulamanın birçok yerinde kullanılıyordu ve kodların değiştirilmesi uzun sürecekti.
Identity alanının en küçük değerine baktığımda 700 milyonlarda olduğunu gördüm. Yazılımcı ve yönetici arkadaşlarla yaptığımız fikir alışverişinde bu alanda tutulan değerlerin hiçbir anlamı olmadığını, son kullanıcıya gösterilmediğini ve hiçbir yerde kullanılmadığını öğrendim. Yani aslında temel olarak gereksiz bir alandı ve ironik olarak gereksiz bir alan yüzünden kısmen kesinti oluşmuştu. Sonra biraz düşününce bu alandaki değeri neden -2.147.483.648 yapmayalım ki dedim önce kendi kendime, sonra da ilgili yöneticilere. Sonuç itibariyle madem bu değerlerin bir anlamı yoktu, o zaman bu değişiklikle tabloya en az 2,8 milyar daha yeni kayıt konabilir olacaktı; hem de tek bir metadata işlemiyle, zerre kesinti, risk ve uygulama tarafında kod değişikliği olmadan ve zahmetsizce.
Sonuç itibariyle bu çözümü uyguladık ve sorunumuz çözülmüş oldu. Düşündüğümüz gibi hiçbir kesinti veya hata oluşmadı, kimsenin uygulama kodlarını değiştirmesine gerek kalmadı.
Tabii ki her sorun kendine has şartları barındırıyor ve her sorun aynı yöntemle çözülemez. Bu ve benzer sorunlarla karşılaştığınızda soruna aklınıza gelen ilk şeyle hemen müdahale etmek yerine, sorunu birçok açıdan ve olabildiğince resmin büyüğünü görerek değerlendirmeye çalışmanızda ve en verimli çözümü bulmaya çalışıp uygulamanızda fayda var. Özellikle kritik, 7/24 operasyonun olduğu ve kesintiyi kaldıramayacak ortamlar için bu olmazsa olmaz bir gereklilik.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
Tel: +90 530 976 93 59
www.ekremonsoy.com
Dün ve bugün farklı müşterilerde ilginç 2 sorun ile karşılaştım. İkisi hakkında da yazmak istiyorum, ama bugün sanırım sadece birisi için yeterli enerjim var.
Müşteride bazı kontroller yaparken en masraflı sorguları da kontrol ettim. Bu çalışmayı yaparken kullandığım sorgulardan birisi şöyle (yer açısından kod örneğini kısalttım):
SELECT TOP(20)
[qs].[execution_count],
[qs].[total_worker_time],
[qs].[total_worker_time] / [qs].[execution_count] AS [avg_worker_time],
[qs].[total_elapsed_time] / [qs].[execution_count] AS [avg_elapsed_time],
SUBSTRING([qt].[text], ([qs].[statement_start_offset] / 2) + 1,
((CASE qs.[statement_end_offset]
WHEN -1 THEN DATALENGTH([qt].[text])
ELSE [qs].[statement_end_offset] END
- [qs].[statement_start_offset]) / 2) + 1) AS [problematic_statement_text]
FROM sys.dm_exec_query_stats AS [qs] WITH (NOLOCK)
CROSS APPLY sys.dm_exec_sql_text([qs].[plan_handle]) AS [qt]
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);
İnternette de birçok çeşitli örneğini bulabileceğiniz bir kod örneği, özel bir şey yok. Bu kodu çalıştırdıktan sonra oluşan manzaraya ait ekran görüntüsünü de aşağıda paylaşıyorum.
 |
Ekran görüntüsünü büyütmek için üstüne tıklayın. |
CPU açısından en masraflı sorgulara ait istatistikleri incelemek için yukarıdaki kodu çalıştırdıktan sonra karşılaştığım görüntüde kırmızı dikdörtgen ile işaretlediğim çok ilginç bir sorgu dikkatimi çekti. Bu ilginç sorguyu da aşağıda paylaşıyorum:
SELECT A.request_session_id, A.request_request_id, A.resource_type, A.resource_associated_entity_id, A.resource_database_id, A.resource_subtype, convert(nvarchar(100),substring(A.resource_description,1,100)) AS resource_description FROM sys.dm_tran_locks AS A WITH ( NOLOCK ) WHERE A.request_status = 'WAIT'
Not: Bu da kesinlikle özel veya müşterimin kendi yazılımına ait bir sorgu değil.
Sorgunun neden çok ilginç olduğunu şöyle izah edeyim:
1- Sorgu, yukarıda da belirttiğim gibi müşterimin kendi uygulamalarına ait değil,
2- Müşterimin uygulamalarından üretilen sorguların en yüksek CPU masraflısının masrafından 8 kat daha masraflı!
Daha fazla inceleyince, sorgunun 3. parti ve piyasada gayet bilinen ve yaygın olarak kullanılan bir performans izleme uygulamasından geldiğini gördüm. Bu, akıllardaki sorulardan sadece birini cevaplıyor. Bir diğer soru ise neden bu kadar sade olan ve bir Dynamic Management View (DMV)'ü sorgulayan bir sorgunun bu kadar masraflı olduğu.
Sorgunun masrafları hakkında biraz ayrıntı vereyim. Sorgu her çalıştığında 2,6~ saniye sürüyor, neredeyse hiç Read (diskten okuma) yapmıyor, fakat 2,5~ saniye CPU zamanı tüketiyordu. Ayrıca sorgu sürekli olarak çalıştırılıyordu, sanki gerçek zamanlı izleme yapılan bir ekrandan çağrılıyor gibi.
Bu noktada ilk aklıma gelenler:
- Böyle ünlü bir firma, nasıl olur da bu kadar masraflı bir sorguyu bu sıklıkta çalıştırır ve izleyenin izlenenin durumunu bu kadar dramatik olarak değiştirmesine neden olur? (Elbette her izlemenin bir maliyeti vardır, ama bu kadar da değil!)
- Acaba bu ortamdaki SQL Server versiyonuna has bir durum, davranış veya ürün arızası mı söz konusu?
Hemen aynı kodu hiç yük olmayan bir test ortamımdaki SQL Server 2016 ve 2017'de denedim. Sorgu 0ms'de tamamlanıyordu. İlginç! Başka, ama bu sefer canlı/üretim ortamı olan SQL Server 2005, 2008R2, 2012, 2014 ve 2016'larda denedim ve bu noktada sorgunun maliyetinin SQL Server'ın versiyonuna göre değil, kodun çalıştırıldığı ortamdaki işlem yoğunluğuna göre değiştiğini fark ettim. Örneğin hiçbir işlem olmayan test / geliştirme ortamlarında 0ms CPU zamanı tüketen sorgu, ortalama işlem hacmine sahip canlı/üretim ortamlarında 150 - 350ms arasında CPU zamanı tüketiyordu.
Sonuç itibariyle ortaya çıktı ki sorgunun çok CPU zamanı tüketmesinin nedeni SQL Server'ın versiyonuyla ilgili değildi, kodun çalıştırıldığı ortamdaki işlem yoğunluğuyla ilgiliydi. Bununla birlikte ne olursa olsun, bir izleme uygulamasının sistem üstünde bu derecede yük oluşturması bence kabul edilemez. Müşteriye de bu durumu ayrıntılarıyla izah ettim.
Her türlü kritik ortamınızı 7/24 izlemek durumundasınız. Olabildiğince kesintisiz, güvenli, performanslı ve stabil bir hizmet verebilmek için, işinizi riske atmamak için bu bir seçenek değil, zorunluluktur. Fakat sisteminizi izlerken yanlışlıkla performansını kötü etkilemediğinizden, doğru kontrolleri düzgün ve yeteri kadar uyguladığınızdan emin olmanızda büyük fayda var.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
Tel: +90 530 976 93 59
www.ekremonsoy.com
Özellikle son aylarda farklı birçok şirketle oldukça hummalı bir şekilde güvenlik konulu toplantılar ve çalışmalar yapıyoruz. Bunun tek nedeni hiç durmadan ve çeşitli katmanlarda ortaya çıkan donanım ve yazılım açıklarının yanısıra, çeşitli kurumlar tarafından uygulanan harici denetimler ve bu çerçevede ortaya çıkan ihtiyaçlar oluyor. Tabii olarak veritabanları da tüm bu kaosun merkezinde oluyor.
Bakım ve Destek Anlaşması kapsamında danışmanlık hizmeti verdiğim birçok şirkette özellikle son zamanlarda Ernst & Young, KPMG, PWC, PCI gibi uluslararası firmaların yanısıra Finansbank, Abank, TEB, Akbank gibi bankaların çeşitli denetimleri gerçekleşiyor. Yıllardır çok çeşitli kurumlarda, defalarca denetime tabi tutulunca ne zaman, nereden bulgu geleceğini biliyorsunuz. Bu nedenle destek verdiğim ortamlarda varsayılan olarak bu noktalar için zaten gerekli müdahalelerde bulunurum. Fakat bazı tedbirler ancak yeri geldiğinde, gerçekten gerekiyorsa ve yönetimin de desteğiyle alınabiliyor. Örneğin veritabanına gelen işlemlerin kayıt altına alınması gibi. Çünkü bu, ek maliyetler doğurabilecek ve koordinasyon gerektiren bir hamle.
Bir müşterimin geçireceği denetim dolayısıyla Microsoft SQL Server veritabanı ortamındaki bazı kritik tablolarında gerçekleşen kayıt okuma ve değişiklik işlemlerinin kayıt altına alınması gerekiyordu. Yani mesela bir tablodaki kayıt ne zaman, nasıl ve kim tarafından okunmuş veya değiştirilmiş gibi. Bu kapsamda yapılmak istenen kayıt altına alma işleminin hacmi, kapsamı, denetim firmasının ve müşterimin beklentisi, müşterimin ortamı, olanakları ve bütçesi gibi kriterleri değerlendirerek kendilerine bazı tavsiyelerde bulundum. Sonuç itibariyle Microsoft SQL Server'ın önceden başka ortamlarda da (bir banka dahil) kullanmış olduğum bir özelliği olan Database Audit özelliğini kullanmaya karar verdik.
Database Audit özelliğini devreye aldıktan sonra bir şey dikkatimi çekti, SQL cümlecikleri (statement) nedense kırpılmış şekilde kaydediliyordu. Önceden böyle bir durumla hiç karşılaşmamıştım ve buna bir türlü anlam veremedim.
 |
"statement" alanındaki SQL cümleciği kırpılmış olarak kaydediliyor |
Gayet farkındayım ki Windows Application Log dosyasını bu amaçla kullanmak muhteşem bir karar değil; ama Database Audit'in ve diğer benzer mekanizmaların ürettiği kayıtları toplayacak olan uygulamanın bize sunduğu seçeneklerdeki kısırlık nedeniyle Database Audit'in ürettiği kayıtları doğrudan Windows Application Log'una kaydetmek birçok açıdan en mantıklı seçenekti ve ben de bunu uyguladım. Önceki tecrübelerimde Database Audit tarafından üretilen kayıtları doğrudan dosyalara kaydettiğim için ve bir ihtimal yaşadığımız bu sorunun üretilen kayıtların Windows Application Log dosyasına kaydedilmesiyle ilgili olabileceği ihtimaline karşın test etmek için yine bir dosyaya kaydetmeyi de denedim; fakat maalesef sonuç yine aynıydı! SQL cümlecikleri kırpılarak kaydediliyordu.
Testlerden sonra hemen Microsoft'un dokümantasyonunu inceledim ve bu konuda yazılmış olabilecek olası yazıları aradım; fakat konuyla ilgili bir bilgiye ulaşamadım.
Bakım ve Destek Anlaşması kapsamındaki müşterilerimin doğrudan Microsoft ile anlaşması olsun veya olmasın senede 2 defa ücretsiz Microsoft'a çağrı (Case) açılması ve tarafımca bunun takibinin yapılması hakkı da oluyor. Bu kapsamda müşterime bunun belki Database Audit özelliği ile ilgili bir ürün hatası olabileceğini ve dilerlerse Microsoft'a çağrı açabileceğimi söyledim; fakat bunun öncesinde daha hızlı sonuç alabilme ümidiyle şansımı bir de Microsoft'un ilgili forumlarında denemek istedim ve sorumu sorup beklemeye başladım. Bir süre sonra beklediğim cevaplar geldi!
 |
1 günlük bekleyişten sonra gelen cevap ve yanan ampul. |
İyiki de sormuşum, hiç Microsoft'un çağrı süreciyle vakit kaybetmeden sağolsun Tom Philips'ten sorunumuzu aydınlatacak cevabı almıştım. Belli ki ilk incelememde dokümantasyondaki ve sorunumun cevabı olan bu kritik bu sayfayı ıskalamışım:
 |
Microsoft dokümantasyonu |
Özetlemek gerekirse öncedeki Database Audit tecrübelerimde belli ki hiç 4000 karakteri geçen SQL cümleciğine denk gelmemişim veya dikkatimi çekmemiş ve bu nedenle bu davranışı fark edememişim. Halbuki bu durum Database Audit ile ilgili bir sorun değil, özelliğin doğal çalışma mekanizmasıymış. Bir SQL cümleciği 4000 karakteri geçiyorsa Database Audit bu cümleciği "sequence_no" adı altında artan sayı değeriyle cümleciğin sonuna kadar parçalara bölüyormuş. SQL cümleciğinin tamamını okumak için "event_time", "action_id" ve "session_id" alanlarındaki değerleri takip edebilirmişim. Evet, çok pratik değil; fakat nihayetinde bu bir ürün hatası da değil!
Bu gizemi de aydınlattıktan sonra içimiz rahatladı, çünkü şirketin tabi olacağı denetime çok az bir süre kalmıştı ve sorunumuz için muhakkak bir çözüm üretmemiz gerekiyordu. Eğer bu özelliği zamanında hayata geçiremezsek ve SQL cümleciklerinin bu durumunu denetim firmasına açıklayamazsak bu konuda bulgu çıkabilir ve nahoş sonuçlara neden olabilirdi.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
Bu Pazar sabahı neredeyse gün ağarana kadar bakım ve destek anlaşmamız olan çeşitli müşteri ortamlarında Windows güncellemeleri uyguladık. Bu Microsoft SQL Server ortamlarının bazılarında iş sürekliliğini sağlayan Always On Availability Groups veya Failover Clustering gibi teknolojiler kullanılırken, bazıları ise "Stand-alone" tabir edilen, yani iş sürekliliği olmayan ortamlardı.
İş sürekliliği altyapısı olan ortamlardaki Windows güncellemelerinden kaynaklanan kesinti süreleri ortalama 5-8 saniye ile sonlanırken, iş sürekliliği olmayan ortamlarda bu süre 5-10 dakikalara kadar çıktı. İş sürekliliği olmayan ortamlar için bu nispeten belirsiz bir süre, çünkü güncellemeden kaynaklı çıkabilecek olası bir sorun, böyle bir ortamdaki kesinti süresini çok daha fazla uzatabilir. Halbuki iş sürekliliği olan bir ortamda güncellemeler önce pasif olan sunucularda uygulandığı için herhangi bir aksilik güncellemeler henüz canlı sisteme uygulanmadan büyük ihtimalle fark edilir. Gerekiyorsa pasif olan sunucu tamamen yeniden kurulabilir, ama sonuç itibariyle doğru kurgulanmış bir canlı sistemde herhangi bir kesinti oluşmadan sorun atlatılmış olur.
Peki iş sürekliliği kimler için gerekli? Bugüne kadar birçok sektörden birçok şirketle çalışma şansı buldum ve gördüm ki, iş sürekliliği "şu sektörler için olmazsa olmaz, bu sektörler için olmasa da olur" denilerek genelleme yapılabilecek bir konu değil. Örneğin bazı sağlık veya finans kurumları 7/24 hizmet verirken, bazıları 5/8 hizmet verebiliyor. İş sürekliliği, bir şirketin verdiği hizmetler ve hedefleri kapsamında seçilebilecek bir yöntem. Bununla birlikte, eğer bir şirket 7/24 hizmet veriyorsa iş sürekliliğini muhakkak ciddiye almalıdır diye düşünüyorum.
Mesela küçük bir test yapalım. IT veya Sistem Yöneticisi olarak yönetiminizde olan veritabanı ortamlarınız için şu sorulara nasıl yanıt verirdiniz?
"Tahammül edebileceğiniz en uzun veritabanı kesinti süresi nedir?"
"Canlı veritabanı ortamınızdaki olası bir sorun/kesinti hakkında son kullanıcılar tarafından mı haberdar ediliyorsunuz?"
"Canlı veritabanı ortamınızda bir kesinti oluşması durumunda, veritabanlarınızı en kısa ne kadar sürede tekrar çalışır duruma getirebilirsiniz?"
Tabii ki bu konudaki sorular bunlarla sınırlı değil, hatta bunlar sadece bir başlangıç; ama iyi bir başlangıç.
İş sürekliliğinden ayrı olarak bu sabahki çalışma kapsamında kesinti yaşanan ortamların bazılarında kesinti nedeniyle alınan hataların doğrudan son kullanıcıya yansıtıldığını gördüm. Bir son kullanıcı gözüyle böyle bir durumun bir şirketin imajı açısından hiç de hoş olmadığını düşünüyorum. Bir profesyonel gözüyle de veritabanı ile ilgili hataların doğrudan son kullanıcılara ve potansiyel saldırganlara alenen ifşa edilmesini güvenlik açısından hiç doğru bulmuyorum. Bu sorun, iş sürekliliği olsun veya olmasın her halükarda gerçekleşebiliyor. Tabii iş sürekliliği olan ortamlarda bu sorun birkaç saniye sürerken, diğer ortamlarda uzun dakikalar boyunca sürebiliyor.
İş sürekliliği şansa bırakılacak kadar ucuz bir konu değil. Bazı ortamlardaki 10 dakikalık kesintinin sadece maddi bedeli dudak uçuklatacak kadar yüklü olabiliyor.
Az kesintili, bol huzurlu günler dilerim.
Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com
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

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ı
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.
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
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

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
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
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