Masters Of SQL

SQL Server ile ilgili bilgiler, hayata dair paylaşımlar ve birazda eğlence tabii...
Deadlock’sız, Blocking’siz, Contention’sız günler diliyoruz :)
Sysadmin sizinle olsun

DBA Toolkit (sp_WhoIsactive)

Evet sevgili SQL Server sevenler, sevmek zorunda kalanlar ve nereden bulaştım bu işe diyenler :). Yeni bir bölüme başlıyoruz "DBA Toolkit" amacımız genelde DBA ler tarafından kullanılan (ki en çok kendimizin kullandığı) veya kullanılmasını tavsiye edeceğimiz scriptleri tanıtıp paylaşacağız.

Serimize hayat kurtaran baş tacımızla :) başlıyoruz.

Tüm DBA ler için "Sistem yavaşladı" veya "Kitlendik" sözlerini duydumu yoğun arayış başlıyor demektir. Önce "Activity Monitor" açılmaya çalışılır açılırsa sorgular kontrol edilir eğer açılmazsa araştırma devam eder ve ellerinde bulunan query lerle (sp_who veya sp_who2 en çok kullanılanı) inceleme yapılmaya devam edilir ve uzun bir arayıştan sonra (bu arada kitlenme bitmiş olabilir :):)) "SQL de sorun yok" sözleriyle biter.

sp_WhoIsActive Download



İndirdiğiniz scripti direk SSMS üzerinde execute ederek sistemimize ekliyoruz, master db üzerinde çalışan bir SP olduğundan dolayı belirli yetkilere sahip olmanız gerektiğini hatırlatmama gerek yoktur herhalde :). Siz yapamıyorsanız sysadmin'e söyleyip (yararını görmesi için makaleyi okutabilirsiniz) execute ettirebilirsiniz.

Size sisteme aldığınız script için "New Query" diyerek yeni bir sayfa açıp execute etmek kalıyor.
    EXEC sp_WhoIsactive
    



Görüldüğü gibi sistem hakkında fazlasıyla bilgi içeriyor.



Kullanım parametrelerini öğrenmek için
    EXEC sp_whoisactive @help = 1
    




Çok fazla kolon geliyor ben sadece belirli kolonları istiyorum acaba "Adam" amca bunları düşünmüş mü? dediğiniz duyar gibiyiz ve cevabımız "Yapmış be adam :):) "
    EXEC sp_WhoIsActive		
     @find_block_leaders = 1
   , @get_task_info = 1
   , @get_additional_info = 0
   , @output_column_list = '[session_id][block%][login_name][host%][host_process_id][program%][sql_text][wait_info]'
   , @sort_order = '[blocked_session_count] DESC'
    




DBA ler için belki de en önemli bölümü (her türlü gideri varda :) ) sistemi bloklayan sorguyu çok hızlı bir şekilde gösteriyor olması. Bunun için kolonlar içerisinde "blocking_session_id" kontrol etmemiz yeterli oluyor. Burada yazan SPID bizi kilitleyen sorgunun ID si bu SPID yi kontrol ettikten sonra beklemeye devam edilebilir veya hiç istemesekte yapmak zorunda olduğumuz "Kill" komutunu çalıştırabiliriz.
    EXEC sp_whoisactive @help = 1
    




Sorgularınız uzun olduğunda XML olarak çıkan sonuç sizi tatmin etmeyebilir, bunun için alttaki şekilde çalıştırabiliriz.
     EXEC sp_whoisactive @format_output = 0
    


SQL Server'da gelen connectionların bazıları sleeping de beklerler bunları bulabilmek için (Yazılımcıların açık bıraktığı sorguları görmekte bire bir :) )
    EXEC sp_WhoIsActive @show_sleeping_spids = 2
    


Sorguların query_plan larını görebilmek için.
    EXEC dbo.sp_WhoIsActive @get_plans = 1, @get_task_info = 2
    




Çok fazla veri tabanıyla çalışan DBA'ler için güzel bir parametre de filtre parametresi.
    -- İstediğimiz veri tabanına göre filter koyuyoruz
    EXEC sp_whoisactive @filter_type = 'database', @filter = 'master'
    GO
    -- Görmek istemediğimiz veri tabanına göre filter koyuyoruz
    EXEC sp_whoisactive @not_filter_type = 'database', @not_filter = 'master'
    


Son olarak da sp_WhoIsActive in sorgu sonuçlarını bir tabloda toplayıp bunlar üzerinde sonradan analiz yapmaya çalışalım.

Adım 1:
Öncelikle alt yapımızı hazırlayalım.
    -- sp_WhoIsactive nin sorgu sonucuna göre birr tablo create ediyoruz
    DECLARE @History_table VARCHAR(4000) ;
    SET @History_table = 'spWhoIsActiveHistory';

    DECLARE @schema VARCHAR(4000) ;
    EXEC sp_WhoIsActive
    @get_transaction_info = 1,
    @get_plans = 1,
    @return_schema = 1,
    @schema = @schema OUTPUT ;

    SET @schema = REPLACE(@schema, '
', @History_table) ;

    -- PRINT @schema 
    EXEC(@schema) ;
    


Adım 2:
Hazırladığımız tabloya "@destination_table" parametresini kullanarak belli aralıklarla kayıt atacağız ve böylece geçmiş yönelik analiz yapabileceğiz. sp_WhoIsactive SP sini çok farklı şekilde çalıştırabildiğimizi unutmayalım dikkatli olmanız gereken nokta history tablosunu hangi parametrelerle oluşturduysak o parametrelerle ilerlememizdir. Biz burada Execution planları almak istediğimizden dolayı "get_plans" parametresiyle çalıştırdık. "EXEC sp_WhoIsActive @get_transaction_info = 1, @get_plans = 1"
    DECLARE
    @History_table VARCHAR(4000) 
    SET @History_table = 'spWhoIsActiveHistory';

    -- Anlık olarak kayıtları ekliyoruz
    EXEC dbo.sp_WhoIsActive @get_transaction_info = 1, @get_plans = 1,
                @destination_table = @History_table;

    -- Eklenen kayıtları kontrol ediyoruz
    select * from spWhoIsActiveHistory order by collection_time desc
    


Adım 3 :
Bu kayıt işlemini belli bir tekrarla otomatik olarak yapmak isteyebiliriz.
    DECLARE
        @History_table VARCHAR(4000) ,
        @msg NVARCHAR(1000) ;

    SET @History_table = 'spWhoIsActiveHistory';

    DECLARE @numberOfRuns INT ;
    SET @numberOfRuns = 10 ;

    WHILE @numberOfRuns > 0
        BEGIN;
            EXEC dbo.sp_WhoIsActive @get_transaction_info = 1, @get_plans = 1,
                @destination_table = @History_table ;

            SET @numberOfRuns = @numberOfRuns - 1 ;

            IF @numberOfRuns > 0
                BEGIN
                    SET @msg = CONVERT(CHAR(19), GETDATE(), 121) + ': ' +
                     'Lütfen bekleyin loglama devam ediyor...'
                    RAISERROR(@msg,0,0) WITH nowait ;

                    WAITFOR DELAY '00:00:05'
                END
            ELSE
                BEGIN
                    SET @msg = CONVERT(CHAR(19), GETDATE(), 121) + ': ' + 'Loglama Bitmiştir..'
                    RAISERROR(@msg,0,0) WITH nowait ;
                END

        END ;
    GO

    -- Eklenen kayıtları kontrol ediyoruz
    select * from spWhoIsActiveHistory order by collection_time desc

    


"Her yiğidin bir yoğurt yiyişi vardır" der atalarımız bu yüzden bu güzelim SP yi kullanırken Bizde onlarca kolon içerisinde nelere çok dikkat ediyoruz onlardan bahsedeyim.
Hatırlarsak bu değerlere "EXEC sp_whoisactive @help = 1" yazarak ulaşabiliriz

"[dd hh:mm:ss.mss]" - Tabii ki ilk sırada :) neye dikkat ediyorum hangi query ne kadardır devam ediyor. Her uzun süren sıkıntılıdır diyemeyiz tabii bununla birlikte sorumlusunu bulup bir mütaala :):) yapıyoruz.
"[sql_text]" - Query içeriğini buradan görebiliyoruz.
"[login_name]" - Query yi çalıştıran arkadaşı tespiti hızlandırıyor :) Seni seçtim pikachu derken ispatınız oluyor :):)
"[wait_info]" - Yine önemli kolonlardan biri özellikle blocking yapan querylerde wait süresini gözlemliyorum query analizlerinde sıkıntılı bölgeye odaklanmayı kolaylaştırıyor.
"[blocking_session_id]" - Kritik kolonlardan biri, Query leri blocklayan query'nin SPID sini gösteriyor.
"[physical_reads]" - IO baskısı yapan queryleri üzerinde çalışma yapmak için bakıyoruz. Tam bir rakam söylemek zor çünkü; bazen 10.000 yüksekken bazen de 100.000 yüksek oluyor.
"[query_plan]" - Query'nin Execution Planını görüp incelemek için kullanıyoruz.
"[percent_complete]" - özellikle Backup-restore işlemlerinde direk baktığımız yer. "Abi bitmedi mi?" sorusunun canlı cevabı :):)
"[host_name]" - Query hangi sunucudan geliyor onu buluyoruz ve kaçağı tespit ediyoruz.
"[database_name]" - Çalışan veri tabanını tespit ediyoruz.
"[program_name]" - özellikle sisteme sızan :):) kaçak kod yazan ki canlı örnekleri çoktur yazılımcı arkadaşlar kullanıcı adı ve şifresini öğrendi mi tutabilene aşkolsun :):).


Bir yazımızda böylece bitti, yeni makalelere blocking'siz select atmak üzere hoşçakalın :).

Nedir Bu SQL Server AUDIT? (Bölüm 2)

Merhabalar :)

Audit Yazı dizimizin 2.bölümü ile karşınızdayız. Bir önceki bölümde "Audit nedir?", "Nasıl kurulur?" sorularının cevabını vermeye çalıştık.

Yazımızın 1.bölümüne gitmek için : Nedir Bu SQL Server AUDIT? (Bölüm 1)

Bu bölümüzde, Auditi’imizin analizini yapmaya çalışacağız. İlk olarak bakalım bir önceki bölümümüzde kurduğumuz Audit’imizi kurabilmiş miyiz? Bunun için; fn_get_audit_file fonksiyonu, Audit’imizin için en sık kullanacağımız fonksiyon olabilir. Fonksiyona, Audit’imizin Path’ini vererek aşağıdaki gibi çalıştırıyoruz.


    
select * from fn_get_audit_file ('D:\Audit\*.sqlaudit',default,default)

Bu fonksiyon sayesinde Audit’imize düşen logları görebiliriz. Sorguyu kendimize göre düzenleyerek, daha okunabilir bir hale getirebiliriz.
    
select event_time, object_name, statement, database_name, class_type, session_server_principal_name, server_principal_name, action_id, succeeded, session_id 
from fn_get_audit_file ('D:\Audit_Deneme\*.sqlaudit',default,default) 
order by 1 desc

Tablodaki kolonları inceleyecek olursak, yapılan işin ne zaman yapıldığını, hangi statement'ın çalıştığını, kim tarafından yapıldığını, yaptığı işin başarılı olup olmadığı gibi soruların cevabını bulabiliriz.

DMV lerle inceleyecek olursak;
    
select * from sys.dm_audit_class_type_map

fn_get_audit_file fonksiyonundan dönen class type seçeneklerini inceleyebilmemize olanak sağlayan bir DMV.

    

select * from sys.server_audits
select * from sys.server_audit_specifications
select * from sys.server_audit_specification_details

DMV leri sayesinde, auditlerimizin detayını görüntüleyebiliyoruz. Şimdi, Auditimizi test etme zamanı:) Bakalım, gerçekten de loglayacak mı?
Çalışma amaçlı bir DB oluşturuyorum.
    
CREATE DATABASE BAKALIM_OLCAKMI

Audit'imize bakalım. İstediğimiz şekilde loglamış mı?
    
select event_time, object_name, statement, database_name, class_type, session_server_principal_name, server_principal_name, action_id, succeeded, session_id 
from fn_get_audit_file ('D:\Audit_Deneme\*.sqlaudit',default,default) 
order by 1 desc

Bu seferki denememizde tablo create, alter, drop işlemlerini deniyoruz.
    
--Tablo create 
USE [BAKALIM_OLCAKMI]
GO

CREATE TABLE [dbo].[Audit_Deneme](
	[column_1] [int] NOT NULL,
	[column_2] [int] NULL
) ON [PRIMARY]

--Tablo alter(kolon ekleme)
ALTER TABLE dbo.Audit_Deneme
	ADD deneme int NULL

--Tablo drop 

DROP TABLE dbo.Audit_Deneme

Az evvelki scriptimizi yeniden çalıştırıyoruz. Bakalım loglamış mı?


Şimdi de yeni bir login oluşturup, daha sonrasında drop ederek loglayacak mı bakalım :)
    
--Login create
USE [master]
GO
CREATE LOGIN [AuditDeneme] WITH PASSWORD=N'12345', 
DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO

--Login drop
DROP LOGIN [AuditDeneme] 
GO

Aynı şekilde, sizler de SP, function, Index create ederek, alter ya da drop yaparak deneyebilirsiniz. Logladığını göreceksiniz :)

Geldik bir yazımızın daha sonuna. Umarım sizlere faydalı olabilmişizdir. Bir sonraki yazı dizimizde görüşmek üzere. Soğuklar da geliyor, kendinize iyi bakın, Yoda’nın tabiriyle “DBA hastalanmaz”. Geçen sene beni nasıl şartladıysa “DBA hastalanmaz” diye kendime telkin ede ede hastalanmadım da gerçekten :D 

Sağlıklı, bol motivasyonlu günleriniz olsun :)


Nedir Bu SQL Server AUDIT? (Bölüm 1)

Merhaba güzel insanlar, görüşmeyeli nasılsınız? Bugün bir Audit yazısıyla karşınızdayız. Aradığınızı bulmanızı, bulamadığınızı sormanızı temenni eder, iyi okumalar dilerim :)

Gelelim Audite :)

SQL Server dünyasına 2008’de giren Audits özelliği, security anlamında DBA’lere güzel avantajlar sağlayan bir özelliktir. Örneğin; server üzerinde kim database oluşturmuş, kim database silmiş, kim bir değişiklik yapmış, yeni oluşturulan bir login bilgisi, incelemek istediğimiz bir tabloya kim kayıt eklemiş, kim kayıt silmiş tarzında sorularımıza cevap bulabileceğimiz, veri tabanımızda belirlediğimiz çerçevede güvenliğimizi sağlayabilmemize olanak sağlayan, 2012 de filter seçeneği ile filtreleme de yapabildiğimiz ekstra yeni özelliklerle hayatımıza dahil olan, incelenmesi gereken bir özelliktir.

Ne dersiniz? Beraber yapalım mı basit bir Audit örneği :)

Security’nin altındaki Audits’e tıklarak “New Audit” diyoruz.


Karşımıza Create Audit ekranı çıkıyor.


Bu ekranda,
Audit name kutucuğunda, oluşturacağımız Audit’e isim vermemiz gerekiyor.
Queue delay kutucuğu default değeri 1000 ms olarak geliyor. Bunun anlamı, biriktirilen verilerin, kayıt yerindeki dosyamıza her bir saniyede bir yazılacağını ifade etmektedir. Bu değer’i 0 yaparsak, eş zamanlı yazılacağı anlamına gelir.
On Audit Log Failure seçeneğinde seçeneğinde Audit’imizin fail olması durumunda ne olacağını seçmemizi istiyor. “Shut Down Server” a dikkat etmenizi tavsiye ederim. Kaş yaparken göz çıkarmayalım :P
Audit Destination’da Audit’imizin nereye yazılacağını seçmemiz gerekiyor. 

Seçeneklerimiz File, Security Log ve Application Log. Ben, D’nin altında açtığım Audit klasörünün altına yazmasını istediğim için file’ı seçiyorum.


Audit File Maximum Limit kutucuğunda ulaşabileceği maximum file sayısını belirleme imkanı sunuyor bize sevgili SQL Server.
Filter seçeneği, aslında bizim yazdığımız query’lerdeki where kısmı. Buraya nasıl bir filtreleme yapmak istiyorsak, o şekilde yazabiliyoruz. Örneğin; ben içinde truncate geçen statementları loglamamasını istedim. 



İster OK’a basarak, Audit’imizi oluşturabilir, istersek Sol üst köşedeki Script’e tıklayarak, penceremizde açılan scripti çalıştırarak Audit’imizi oluşturabiliriz.

    
USE [master]
GO

CREATE SERVER AUDIT [Audit_DDL]
TO FILE 
(	FILEPATH = N'D:\Audit'
	,MAXSIZE = 0 MB
	,MAX_ROLLOVER_FILES = 2147483647
	,RESERVE_DISK_SPACE = OFF
)
WITH
(	QUEUE_DELAY = 1000
	,ON_FAILURE = CONTINUE
)

WHERE statement not like '%truncate%'
   
Auditimizi oluşturduk. Fakat defaultta oluşturduğumuz Audit disable gelir. Bu sebeple Auditimizin üzerine sağ tıklayarak enable duruma getiriyoruz.


Auditimizi oluşturmuş olsak da halen hedefimize ulaşmış sayılmayız. Şimdiki adımımızda, Server bazlı obje değişikliklerini, yeni oluşturulan loginlerin loglamasını hedeflediğimiz bir server bazlı Audit oluşturarak, bu Auditimizi kullanmasını sağlamalıyız. Bunun için, Server Audit Specifications’a sağ tıklayarak New Server Audit Specification… a tıklıyoruz.

Karşımıza çıkan pencerede, neleri loglamasını istiyorsak seçiyoruz. Ben yeni oluşturulan veya silinen bir database i loglaması için Database Change Group, server düzeyinde obje değişikliklerini yakalaması için Schema Object Change Group u ve Login create- drop larını yakalayabilmek için Server Principal Change Group u seçiyorum. Siz isterseniz, kendi ihtiyaçlarınıza göre farklı kombinasyonlar yapabilirsiniz.


Aynı şekilde, pencereden Ok a basarak veya sol üst köşeden aldığımız Script ile Server Bazlı Auditimizi oluştururuz.
USE [master]
GO

CREATE SERVER AUDIT SPECIFICATION [Server_DDL]
FOR SERVER AUDIT [Audit_DDL]
ADD (DATABASE_CHANGE_GROUP),
ADD (SCHEMA_OBJECT_CHANGE_GROUP),
ADD (SERVER_PRINCIPAL_CHANGE_GROUP)
   
Yine, enable etmek gerekiyor tabi :) Audit oluşturma işlememiz tamamlandı. Auditimizin kontrolleri bir sonraki bölümümüzde :) Bakalım Auditimiz olmuş mu? 

Auditimizi DMV ve function ile nasıl incelendiğimizi anlattığımız 2.bölüm için: Nedir Bu SQL Server AUDIT?(Bölüm 2)