26 Haziran 2019 Çarşamba

Bir Sorgu Çalıştırma Planını Görmek İsteyip Göremediğinizde...

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

29 Nisan 2019 Pazartesi

Query Store - Tecrübe

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


11 Mart 2019 Pazartesi

SQLBits'ten notlar

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

14 Ocak 2019 Pazartesi

HATA MESAJI: The distribution agent failed to create temporary files in 'C:\Program Files\Microsoft SQL Server\130\COM' directory. System returned errorcode 5. (Source: MSSQL_REPL, Error number: MSSQL_REPL21100)

HATA MESAJI:
The distribution agent failed to create temporary files in 'C:\Program Files\Microsoft SQL Server\130\COM' directory. System returned errorcode 5. (Source: MSSQL_REPL, Error number: MSSQL_REPL21100)

AÇIKLAMA:
Replikasyonunuz sorunsuz çalışırken bir gün Distribution Agent'ınız böyle bir hata alarak durabilir. Haliyle replikasyonunuz da durur ve yukarıdaki hata mesajını görürsünüz.

Benim senaryomda ben bu sorun ile Transactional Replication kullanırken karşılaştım. A sunucum Publisher idi, Distribution veritabanım da A sunucusundaydı. B sunucusu da Subscriber idi ve Pull yöntemiyle A sunucusuna bağlanıp replikasyon ile aktarılacak işlemleri uyguluyordu.


ÇÖZÜM:
Bahsi geçen hata mesajı A sunucusundan geliyordu. Bu nedenle öncelikle A sunucusuna odaklandım. Aslında hata mesajı kendi içinde net, belli ki Distribution Agent (DISTRIB.exe) 'C:\Program Files\Microsoft SQL Server\130\COM' yolunda bazı geçici dosyalar oluşturmak istiyor; fakat yetkisi olmadığı için (errorcode 5 "Access is denied" demektir) bu hatayı alıyor.

Haliyle ben de A sunucusundaki 'C:\Program Files\Microsoft SQL Server\130\COM' yoluna SQL Server Database Engine servisi için yazma yetkisi verdim. Fakat sorunun hala çözülmediğini gördüm. Sonra aklıma replikasyon için farklı bir Domain hesabı kullandığım geldi, bu sefer "COM" klasöründe bu kullanıcı için yetki verdim; fakat sorunum hala çözülmemişti.

Sonra aklıma Microsoft'un sağ gösterip sol vurduğu eski hatıralarım geldi. Distribution Agent'ın da B sunucusunda olduğunu anımsayınca eski dost Microsoft'un benimle yine maytap geçtiğini anladım. İlgili kullanıcılara B sunucusundaki "COM" klasöründe yetki verince sorunum çözülmüş oldu.

31 Ekim 2018 Çarşamba

Kişisel Verilerin Korunması Kanunu Kapsamında SQL Server ile Neler Yapılabilir?

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.

Kangal: Çoklu hatalı giriş denetimi


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:


Kangal: Anormal bağlantı denetimi


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.

Kangal: Toplu sorgulama denetimi


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.

Kangal: Güçsüz şifre denetimi


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