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.