29 Ocak 2008 Salı

SQL Server 2008: Table Valued Parameters

Son güncelleme tarihi: 10 Nisan 2023

Merhaba arkadaşlar,

"Tablo-değerli parametreler" SQL Server 2008 ile birlikte gelen bir yeniliktir. "Tablo-değerli parametreler", User-Defined Table Type (Kullanıcı Tanımlı Tablo Tipi) kullanılarak tanımlanır. "Tablo-değerli parametreler"ı Stored Procedure ya da Function' lara geçiçi tablo kullanmadan çoklu kayıt göndermek için kullanabilirsiniz.

Şunu da yazımın başında hemen söyleyeyim, bu yazıyı hazırlarken kullandığım SQL Server 2008 versiyonu CTP5 versiyonudur. RTM versiyonunda değişiklikler olabilir. Bunu şu anda bilmek imkânsız. Bu nedenle daha sonra SQL Server 2008 ile ilgili bu ve diğer yazdığım makaleler ile kullanacağınız SQL Server 2008 RTM versiyonu arasında uyuşmazlık olursa kızmayın bana =)

Konunun örneklerle ve deneyerek daha iyi anlaşılacağını düşündüğüm için yazıma bir örnekle devam etmek istiyorum. Meselâ SQL Server 2005 ve öncesinde bir Stored Procedure kullanarak bir kerede birden çok kayıt girmek istediğimizde ne yaptığımızı hatırlayalım. Örneği yapmak için aşağıdaki kodları SQL Server Query Editor \ Query Analyzer'a kopyalayıp yapıştırarak çalıştırın ve örneğimiz için gereken yapıyı oluşturmuş olun.

Örnek Veritabanı:
CREATE DATABASE DenemeDB

Örnek Tablo:
USE DenemeDB
GO
CREATE TABLE dbo.Personeller(PersonelID int NOT NULL, PersonelAdi nvarchar(100) NOT NULL, PersonelEposta nvarchar(100) NOT NULL)

Örnek Stored Procedure:
USE DenemeDB
GO
CREATE PROCEDURE YeniPersonel
( @PersonelID int,
@PersonelAdi nvarchar(100),
@PersonelEposta nvarchar(100) )
AS
BEGIN
INSERT INTO dbo.Personeller VALUES(@PersonelID, @PersonelAdi, @PersonelEposta)
END

Eğer yukarıda örnek kodları bulunan veritabanını, tabloyu ve Stored Procedure' ü oluşturduysanız, şimdi de tablomuzun içine Stored Procedure' ümüzü kullanarak bir kaç kayıt girelim.

Örnek Kayıtlar:
USE DenemeDB
GO
EXECUTE YeniPersonel 1,'Fatma Mutlu','fatmam@xxx.com'
EXECUTE YeniPersonel 2,'Ali Satılmış','alis@xxx.com'
EXECUTE YeniPersonel 3,'Yasemin Yeter','yaseminy@xxx.com'

Örnek Kayıtları Sorgula:
USE DenemeDB
GO
SELECT * FROM Personeller


İşte SQL Server 2008 öncesinde birden fazla kayıt girmemiz gerekdiğinde (genelde) yaptığımız şey buydu. Tablo-değerli parametreler ile karşılaştırıldığında bu yöntemin aşağıdaki gibi bazı eksileri var:

- Birden çok kere gidip gelme (Round Trip)
- Stored Procedure' ün birden fazla çalıştırılması
- Verimsiz kodlama

Aynı sonucu bir de Tablo-değerli parametreler kullanarak almayı deneyelim. Ama önce, yeni örneğimiz için de kullanacak olduğumuz "Personeller" isimli tablomuzdaki kayıtları aşağıdaki kodu kullanarak temizleyelim.

"Personeller" Tablosunu Temizle:
USE DenemeDB
GO
TRUNCATE TABLE dbo.Personeller

Şimdi temiz bir "Personeller" tablomuz var. Tablo-değerli parametrelerimizi bir User Defined Table Type tanımlayarak oluşturalım:

Used Defined Data Type:
CREATE TYPE PersonellerTableType AS TABLE (PersonelID INT, PersonelAdi nvarchar(100), PersonelEposta nvarchar(100));
GO

Bu kodu çalıştırdıktan sonra "DenemeDB" veritabanınız içerisindeki Programmability\Types\User-Defined Table Type içerisinde Resim-1' deki gibi "PersonellerTableType" adında bir User Defined Table Type göreceksiniz.


Resim-1



Şimdi "PersonellerTableType" adlı bu User Defined Table Type'ı kullanarak veri kaydedeceğimiz Stored Procedure' ümüzü oluşturalım. Yalnız şuna dikkatinizi çekmek istiyorum ki bu Stored Procedure' ün adını bir önceki örnekte oluşturduğumuz Stored Procedure ile karıştırılmasın diye özellikle "YeniPersonel08" yaptım. "YeniPersonel08" isimli Stored Procedure' ü oluşturmak için aşağıdaki kodu çalıştırın:

Örnek Stored Procedure:
USE DenemeDB
GO
CREATE PROCEDURE YeniPersonel08
( @PersonelBilgileri PersonellerTableType READONLY)
AS
BEGIN
INSERT INTO dbo.Personeller SELECT * FROM @PersonelBilgileri
END


Stored Procedure de oluşturulduktan sonra sıra veri girmede. Aşağıdaki kodu kullanarak ve tabii User Defined Table Type marifetiyle veri girişi yapmış olacağız:

Örnek Kayıt Girişi:
USE DenemeDB
GO
DECLARE @YeniPersonel PersonellerTableType
INSERT INTO @YeniPersonel VALUES(1,'Zeynep Yamalı','zeynepy@xxx.com')
INSERT INTO @YeniPersonel VALUES(2,'Zeydi Kaçar','zeydik@xxx.com')
INSERT INTO @YeniPersonel VALUES(3,'Mehmet Tanrıverdi','mehmett@xxx.com')
EXECUTE YeniPersonel08 @YeniPersonel
GO

"YeniPersonel" isminde bir değişken tanımladık ve veritipini de daha önceden oluşturmuş olduğumuz "PersonellerTableType" olarak verdik. Daha sonra tanımladığımız bu değişken içerisine eklemek istediğimiz kayıtları INSERT INTO komutunu kullanarak sunucuya tekrar tekrar gidip gelmeden ekledik. Daha sonra tek seferde bu üç kaydı da "YeniPersonel08" ismiyle oluşturmuş olduğumuz Stored Procedure' ü kullanarak tek seferde veritabanımıza kaydettik. Bunu söylemeye gerek var mı ya da yok mu tam bilemiyorum, ama komutun çalışması tamamlandıktan sonra değişkene atadığınız değerler otomatik olarak silinecektir.

Bunu daha önceden şu vey bu şekilde yapıyorduk zaten diyenleriniz olabilir. Fakat SQL Server ile bütünleşik şekilde ve bu kadar kolay bir şekilde böyle bir özellik yoktu. Oldukça kullanışlı olduğuna inandığım bir yenilik. Benim çok hoşuma gitti, umarım siz de beğenirsiniz.

Kaynaklar:
Bu makaleyi hazırlarken Microsoft Virtual Labs dökümanlarından yararlandım.


Ekrem Önsoy

25 Ocak 2008 Cuma

SQL Server 2008: Declarative Management Framework

Yazarın Notu:
Bu makalenin daha okunaklısını buraya tıklayarak okuyabilirsiniz.


Merhaba arkadaşlar,


Bu yazımın konusu, SQL Server 2008 ile birlikte gelen Declarative Management Framework (DMF). Yazımın devamında, size ilk önce DMF' in kavramlarından ve bileşenlerinden bahsedeceğim, daha sonra da DMF' i ne gibi işlerde kullanabileceğimize dair iki örnek vereceğim ve adım adım resimlerle oluşturulmuş bir örnek yapıp yazımı tamamlayacağım.

Bu makalemi hazırlarken kullandığım SQL Server 2008, CTP5 versiyonudur. CTP versiyonlarını kesinlikle Production ortamınıza kurmanızı önermem. Microsoft' un kalbi olan Redmon' tan konuştuğum SQL Server ile çalışan insanlar bana SQL Server 2008' in Ağustos ayından önce çıkmayacağını söylediler. Yani RTM' e daha çok var. Bu makalemdeki örnekleri yapmak için Sanal Makine kullanmanızı tavsiye ederim.

Ben örneklerimi ve testlerimi MyDB isimli bir veritabanında oluşturuyorum. Hiç bir özelliği yok, alelade bir veritabanıdır kendisi ve arzu ederseniz aşağıdaki komutu kullanarak oluşturabilirsiniz.

=====================
CREATE DATABASE [MyDB]
=====================

Peki nedir bu DMF, ne işe yarar? DMF, kısaca Veritabanı Yöneticileri için gerçekten işe yarayacak, yönetimsel olarak istemediğimiz veya istediğimiz şeylerin bir veya birden çok SQL Server Instance' ında Policy tabanlı olarak uygulanışını denetleyecek, bu sayede de işlerimizi kolaylaştıracak bir yönetim sistemidir.

DMF bir kaç bileşenden oluşuyor. Bunlar:
- DMF Managed Target (Yönetilen Hedef),
- DMF Facet (Bu kelimenin tam karşılığını bilemiyorum ama sanırım 'Model' diyebiliriz),
- DMF Conditions (Koşul),
- DMF Policy (Politika),
- DMF Policy Category (Politika Kategorisi),
- DMF Execution Mode (Çalıştırma Modu), ve
- Effective Policy (Etkin Politika)' dir.

Resim-1

Gözünüzü korkutmasın sakın bu terimler. Ne kadar basit olduklarını verdiğim örneklerde ve kendiniz uygularken göreceksiniz. Basit derken yönetimsel olarak basit demek istedim, işlevleri ise çok işe yarar ve güçlü.

Şimdi size tek tek bu bileşenlerden bahsetmek istiyorum. Nedir bunlar? Ne işe yararlar? Bunları anlatacağım.

DMF Managed Target:
Bir SQL Server Database Engine örneği, bir veritabanı, bir tablo ya da bir dizin (Index) gibi DMF tarafından yönetilen varlıklara DMF Managed Target denir.

DMF Management Facet:
Belli bir Managed Target' ın davranış veya karakteristiğini modelleyen mantıksal özellikler bütünüdür. Özelliklerin sayısı ve karakteristikleri Facet içerisinde inşa edilmiştir ve sadece yapıcısı tarafından eklenip çıkarılabilirler. Bir hedef tipi bir veya daha fazla Facet içerebilir ve bir Facet de bir veya daha fazla hedef tipi tarafından içerilebilir.

DMF Condition:
Bir DMF Managed Target' ın izin verilen durumlarını Management Facet' e göre belirleyen bir Boolean beyandır.

DMF Policy:
Bir DMF Condition ve beklenen davranış biçimidir; örneğin, Execution Mode, Target Filters ve Schedule gibi. Bir Policy sadece bir Condition içerebilir. Policy' ler kullanılabilir veya kullanılamaz duruma getirilebilirler.

DMF Policy Category:
Policy' leri yönetmeye yardımcı olan ve kullanıcı tarafından belirlenmiş bir kategoridir. Kullanıcılar, Policy' leri değişik Policy kategorileriyle sınıflandırabilirler. Bir Policy sadece bir kategoriye ait olabilir. Veritabanı sahipleri bir veritabanını bir Policy kategorisine üye yapabilirler. Sadece kategorilerine üye olunmuş Policy' ler bir veritabanını yönetebilirler. Tüm veritabanları dolaylı olarak varsayılan Policy kategorisine üyedir.

DMF Execution Mode:
Bir Policy' nin nasıl çalıştırılacağını belirler. İstendiğinde çalıştırılan modlar Check ve Configure' dır. Otomatik çalışma modları ise:
- Changes are attempted, prevent out-of-compliance (Değişiklik yapılmak istendiğinde, kuraldışıysa önle)
- Changes are attempted, log out-of-compliance (Değişiklik yapılmak istendiğinde, kuraldışıysa kayıt tut)
- On Schedule, log out-of-compliance (Zaman ayarlı olarak, kuraldışıysa kayıt tut)

Effective Policy:
Bir hedefin Effective Policy' leri, bu hedefi yöneten Policy' lerdir. Bir hedef ile ilgili bir Policy, sadece aşağıdaki şartlar gerçekleştiğinde etkindir:

- Policy etkinleştirilmişse (Enabled)
- Hedef, Policy' nin hedeflerine aitse.
- Hedef veya hedeflerden bir tanesi bu Policy' yi içeren Policy grubuna üyeyse.



DMF' i nerelerde kullanabiliriz?
Aşağıdaki iki örneği inceleyin lütfen.

- Meselâ şirket politikanız Database Mil veya SQL Mail' in kullanılmasını yasaklıyor. Bu iki özelliğin kontrol edilmesi için bir Policy oluşturulur. Bir yönetici, mevcut ayarları ve Policy' yi karşılaştırır. Eğer ayarlar Policy kurallarına uymuyorsa, yönetici Configure modunu seçer ve Policy SQL Server ayarlarını Policy ile uyumlu hale getirir.

- AdventureWorkds veritabanınızdaki tüm Stored Procedure' larınının isimlerinin AW_ ile başlamasının gerektiğini farzedelim. Bu politikanın zorlanması için bir Policy oluşturulur. Bir yönetici bu Policy' yi test eder ve Policy kurallarına uymayan Stored Procedure' ların bir listesini hazırlar. Eğer gelecekteki Stored Procedure' lar bu isimlendirme standardına uymazlarsa, Stored Procedure' lar için kullanılan oluşturma komutları (CREATE PROC) hata verecektir.

Policy Yönetimi
Policy' ler SQL Server Management Studio kullanılarak oluşturulur ve yönetilirler. İşlemler aşağıdaki gibidir:

1. Yapılandırılacak özellikleri içeren bir DMF Facet seçin.
2. Management Facet' in durumunu belirleyen bir Condition tanımlayın.
3. Condition' ı, hedefleri süzen ek Condition' ları ve Execution Mode' ları içeren bir Policy tanımlayın.
4. Bir SQL Server Instance' ının Policy ile uyuşup uyuşmadığını kontrol edin.

Bir Policy' de hata oluştuğunda, SSMS' teki Object Explorer' da hedefin hemen yanında ve hedefin daha üstündeki düğümlerde kırmızı bir simge şeklinde kritik sağlık uyarısı görünür.

Policy' ler msdb sistem veritabanında tutulurlar. Bir Policy veya Condition değiştirildiğinde msdb veritabanı da yedeklenmelidir.

DMF' i yönetmek için msdb veritabanındaki PolicyAdministratorRole rolüne üye olunması gerekir. Bu rolün, sistem üzerindeki tüm Policy' lerde tam kontrolü vardır. Kontrol, Policy' lerin ve Condition' ların oluşturulması ve düzenlenmesi ve Policy' lerin kullanılabilir veya kullanılamaz yapılmasını kapsar.


DMF ile Adım Adım SP İsimlendirme Standardı Policy' si Oluşturma Örneği
Öncelikle iki adet DMF Condition oluşturacağız, daha sonra Policy' mizi de bu Condition' ları kullanarak oluşturacağız ve testlerimizi yapacağız.

İlk oluşturacağımız Condition' da uygulayacağımız isimlendirme standardının hangi veritabanına uygulanacağını belirleyeceğiz. Bunun için aşağıdaki adımları uygulayın:

- SSMS' i açın ve çalışacağınız SQL Server Instance' ına bağlanın.
- Object Explorer' daki Management düğümünü genişletin. Conditions düğümünün üzerinde farenin sağ tuşuna basın ve açılan menüden "New Condition..." seçeneğine tıklayın. Daha sonra açılan Create New Condition penceresinde Resim-2' deki gibi bir Condition oluşturun.
- Seçeneğe bağlı olarak oluşturduğunuz Condition için bir Açıklama (Description) tanımlayabilirsiniz. Description' ı "Create New Condition" penceresinin sol tarafındaki "General" sekmesinin hemen altında görebilirsiniz.

Resim-2

Bu Condition ile Policy' mizi oluştururken göreceğiniz gibi isim standardının sadece MyDB veritabanındaki Stored Procedure' lere uygulanmasını sağlayacağız.

Şimdi ikinci Condition' ımız olan İsim Standardını belirleme Condition' ımızı oluşturalım.

- Zaten açık olduğunu varsaydığım Conditions düğümünün üzerinde farenin sağ tuşuna basın ve açılan menüden "New Condition..." seçeneğine tıklayın. Daha sonra açılan Create New Condition penceresinde Resim-3' deki gibi bir Condition oluşturun.

Resim-3

Bu ayarlarla, nesnemizin isminin ilk 4 karakterinin 'eko_' olmasını ağlayacağız, gerisi de bu nesneyi oluşturan kullanıcıya kalmış.

Artık Condition' larımızı oluşturmuş olduk, şimdi sıra Policy' de. Bunun için gene Object Explorer' daki Policy düğümünün üzerinde farenin sağ tuşuna tıklayın ve açılan menüden "New Policy..." seçeneğine tıklayın. Daha sonra açılan "Create New Policy" penceresinde Resim-4 ' teki gibi bir Policy oluşturun.

Resim-4

İsim standardımızın sadece Stored Procedure' lere uygulanması için "Against targets:" listesinde sadece StoredProcedure' ün solundaki seçim kutusunu işaretlemeniz gerekiyor. Bu işaret kutusunun sağındaki yazıları tercüme etmemiz gerekirse şöyle edebiliriz: "MyDB veritabanımdaki tüm Stored Procedure' leri belirlediğim isim standardına uydur." Dikkat ettiyseniz MyDB veritabanımız için oluşturduğumuz Condition' ı hemen "Every StoredProcedure" yazısının hemen altındaki "Isim Standarti Uygulanacak Veritabanim" olarak görürsünüz. "eko_" olarak belirlediğimiz isim standardımızı da "Check condition" açılır kutusunda görebilirsiniz.

Execute Mode olarak da "On Change - Prevent" i seçelim. Böylece, bundan sonra belirlediğimiz isim standardına uymadan oluşturulmaya çalışılacak tüm Stored Procedure' lerin oluşturulması engellenecektir.

Ayrıca "Create New Policy" penceresindeki "Enabled" seçim kutusunu sakın es geçmeyin. Çünkü eğer bu kutucuğu işaretlemezsek, Policy' miz etkin hale gelmeyecektir ve isim standardımız uygulanmayacaktır.

Seçeneğe bağlı olarak oluşturduğunuz Policy için de bir Açıklama (Description) tanımlayabilirsiniz. Description' ı "Create NewPolicy" penceresinin sol tarafındaki "General" sekmesinin hemen altında görebilirsiniz.

DMF Policy' mizi Test Edelim!
Peki eğer biz bu DMF Condition ve Policy' leri oluşturmadan önce isim standardımıza uymayan bir Stored Policy oluşturulmuşsa o zaman ne olacak? Policy' mize uymayan nesneleri en kısa yolla nasıl buluruz? Tabii ki Policy' mizi test ederek!

Öncelikle Policy' mizin çalışıp çalışmadığını bir test edelim. Bunun için yeni bir Query açın ve Query Editor penceresinde aşağıdaki kodu çalıştırın.

=====================
USE MyDB
GO
CREATE PROCEDURE Test
AS
SELECT * FROM MyDB
=====================

Bu komutu çalıştırdıktan sonra eğer Conditon ve Policy' leriniz sorunsuz çalışıyorsa Query Editor' deki "Messages" penceresinde aşağıdaki hatayı almanız gerekiyor.

=====================
TEST1(TEST1\lab): Policy 'Isim Standardi' has been violated by 'Server/Database[@Name='MyDB']/StoredProcedure[@Name='test' and @Schema='dbo']'. This transaction will be rolled back. Policy description: '' Additional help: '' : ''. TEST1(TEST1\lab): Msg 3609, Level 16, State 1, Procedure sp_syspolicy_dispatch_event, Line 50 The transaction ended in the trigger. The batch has been aborted.
=====================

Eğer bu hatayı aldıysanız her şey yolunda demektir. Hatayı şöyle tercüme edebiliriz: "test" isimli bir Stored Procedure oluşturmaya çalıştığınız için "Isim Standardi" isimli Policy' yi ihlal ettiniz. Yapılan işlem geri alınacaktır.

Eğer bu hatayı almadıysanız ve "test" isimli SP oluşturulduysa, Policy' nizin etkin olduğundan emin olun. Bunun için Policy' nizi Object Explorer' daki Policies isimli düğümün altında bulabilir ve üzerinde sağ tuşa tıklayabilir ve "Enabled" olduğundan emin olabilirsiniz ya da Policy' nizin özelliklerinden (üzerinde sağ tuş ve açılan menüden Properties' e tıklayarak) "Enabled" seçim kutusunun seçili olduğundan emin olabilirsiniz. Eğer "Enabled" ise ve gene de isimlendirme kuralı işlemiyorsa, o zaman oluşturduğunuz Condition' ları tekrar gözden geçirmenizi tavsiye ederim.

Ayrıca Policy' nizin etkin veya etkin olmadığını simgesinden de anlayabilirsiniz. Eğer Policy' nizin simgesinin sağ alt köşesinde aşağı giden kırmızı bir ok resmi varsa o zaman Policy' niz kullanılmıyor durumundadır.

Şimdi biz Policy' mizi oluşturmadan önceki Stored Procedure' lerle ilgilenebiliriz! Yalnız bu bölümü daha anlaşılabilir yapmak için bir planım var. Umarım "amma uzattın sen de!" demiyorsunuzdur.

Bunun için sizden Policy' nizi yukarıda anlattığım yöntemle kullanılmıyor yapmanızı yani "Disable" etmenizi isteyeceğim. Haklı nedenlerim var! Çünkü isim standardı politikamızı çiğneyen bir Stored Procedure oluşturmamızın tek yolu bu. Böyle bir SP oluşturalım ki, konuyu daha iyi anlamamıza yardımcı olsun.

"Isim Standardi" isimli Policy' yi "Disable" ettikten sonra aşağıdaki kodu kullanarak bir SP oluşturun.

=====================
USE MyDB
GO
CREATE PROCEDURE Test
AS
SELECT * FROM MyDB
=====================

Evet, böylece kuralı çiğneyen bir SP oluşturabildik en sonunda! Şimdi lütfen şu Policy' yi tekrar "Enable" edin. Biliyorum biliyorum, çok masraflıyım!

Şimdi bir de isim politikamıza uyan bir SP oluşturalım. Lütfen aşağıdaki kodu çalıştırın.

=====================
USE MyDB
GO
CREATE PROCEDURE eko_Test
AS
SELECT * FROM MyDB
=====================

Şimdi biri "Test" diğeri de "eko_Test" isimli iki tane SP' miz oldu. Hayırlı olsun. Biri isimlendirme standardımıza uyuyor, diğeri ise uymuyor. Şimdi bunu Policy' mize nasıl otomatik olarak bulduracağımızı göreceğiz.

Bunun için SSMS' teki Object Explorer' da bulunan Management\Policies düğümü altındaki "Isim Standardi" isimli Policy' nizi bulun ve üzerinde farenin sağ tuşuna tıklayın. Açılan menüden "Test Policy..." seçeneğine tıklayın. Aşağıda bulunan Resim-5' e benzer bir pencerenin açılması gerekiyor.

Resim-5

Eğer "Run Now - Isim Standardi" isimli pencereye bakarsanız yukarıda oluşturduğumuz iki SP' yi göreceksiniz. Birisi "Isim Standardi" isimli Policy' ye uyuyor, diğeri ise uymuyor. Aynı penceredeki "Target" isimli sütunda sorunun nedeni yazıyor. Eğer "Details" sütununda bulunan "View..." bağlantısına tıklarsanız karşınıza Resim-6' dakine tıpatıp benzer bir pencere çıkması lâzım.

Resim-6

Bu pencerede hatanın nedenini çok daha kolay görebilirsiniz. Bu pencere, bir önceki Resim-5' teki pencerede bulunan ve Target sütununda yazan ve karmaşık görünen hata mesajının biçimlendirilmiş şeklidir. "Expected Value" sütunu girilmesi umulan değerdir, "Actual Value" sütunu ise girilen değerdir. Belirlediğimiz isimlendirme standardı Policy' mizin sonucu olarak, SP' lerin adlarının ilk dört karakterinin "eko_" olması gerekiyor, fakat bu SP' nin adı böyle değil. İşte bu nedenle bu SP hata veriyor.

Eğer değer True\False gibi bir değer olsaydı Resim-5' teki "Run Now" isimli pencerede bulunan "Configure" etiketli düğmeye tıklayarak gerekli ayarların otomatik olarak yapılmasını sağlayabilirdik. Fakat bu ayar otomatik olarak yapılamaz. Bu nedenle gidip elle "Test" isimli SP' nin adını "eko_Test2" yaparsanız tekrar Policy' yi test ettiğinizde buir hata ile karşılaşmadığınızı göreceksiniz.

Bu değişikliği yapmadan önce Resim-7' ye de bir gözatmanızı istiyorum. Size bu yazımın önceki bölümlerinden biri olan Policy Yönetimi isimli bölümde şöyle demiştim: "Bir Policy' de hata oluştuğunda, SSMS' teki Object Explorer' da hedefin hemen yanında ve hedefin daha üstündeki düğümlerde kırmızı bir simge şeklinde kritik sağlık uyarısı görünür.". İşte Resim-7' de bunu görüyorsunuz. SSMS' teki Object Explorer otomatik olarak Refresh yapmıyor, bu nedenle göremiyor olabilirsiniz, F5' i kullanarak veya Object Explorer' daki Refresh düğmesini kullanarak düğümleri yenileyebilirsiniz. Resim-7' nin sağ tarafındaki "Object Explorer Details" penceresindeki "Policy Health State" e de dikkat edin, "Critical" yazıyor.

Resim-7

Siz de daha değişik Facet' leri ve Condition' ları kullanarak değişik Policy' ler oluşturabilirsiniz, ki oluşturmanızı da tavsiye ederim.

Özetle, size bu makalemde SQL Server 2008 ile birlikte gelecek ve yönetim işlerinde biz Veritabanı Yöneticilerinin çok işine yarayacağını düşündüğüm Declarative Management Framework' ü size anlatmaya çalıştım. Umarım yararı dokunmuştur.


Ekrem Önsoy

10 Ocak 2008 Perşembe

MCT Summit 2008 - Berlin\Almanya

Merhaba Arkadaşlar,

Bu sene Berlin' de düzenlenecek olan MCT 2008 Zirvesi' ne çalıştığım firma olan CompecTA adına ben de katılacağım.

Bu seneki zirvede konusunda çok iyi olan konuşmacılar Windows Server 2008, Visual Studio 2008 ve tabii ki SQL Server 2008' deki yeniliklerden bahsedecekler.

Zirve 3 gün sürecek. Başlangıç tarihi 14 Ocak 2008. Ben 12 Ocak' ta Berlin' de olacağım. Biraz da gezmeye vakit olsun değil mi...

Eğer sağ salim dönebilirsem sizlerle zirvede aldığım notları ve yeni öğrendiğim şeyleri bu sitemde ve SQL Server günlüğümde paylaşacağım umarım.

Ekrem Önsoy

8 Ocak 2008 Salı

The transaction log for database 'verıtabanı adı' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sy

HATA MESAJI:
The transaction log for database 'verıtabanı adı' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases

AÇIKLAMA:
Veritabanınızda bir işlem yaptığınızda bu hatayı alabilirsiniz. Bu hata, Transaction Log dosyanızda yeteri kadar yer olmadığından, yaptığınız işlemin Transaction Log dosyasına kaydedilememesinden kaynaklanmaktadır.

ÇÖZÜM:
Transaction Log dosyanızın, yaptığınız işlemi kaldırabilecek kadar büyük olduğundan emin olun.

Meselâ bazı ortamlarda DML işlemlerinin çok sık olduğunu, fakat Transaction Log dosyasının Auto Growth seçeneğinin sadece 1MB veya 5-10% olduğunu görüyorum. Performans açısından çok büyük bir darbedir bu. Ayarlarınızı tekrar gözden geçirmelisiniz. Hatta bazıları Auto Growth' u kullanmıyorlar ve böylece Transaction Log dosyası dolduğunda veritabanınız kullanılamaz hale geliyor.

Eğer Transaction Log dosyanız için Auto Growth (Otomatik büyüme) seçeneği ortamınıza göre uygun bir şekilde ayarlanmamışsa, ayarları tekrar gözden geçirin.

Recovery Models: FULL, BULK LOGGED, SIMPLE

Merhaba arkadaşlar,

SQL Server' da veritabanlarınız için duruma göre kullanabileceğiniz üç adet Recovery Model bulunmaktadır. Size bu yazımda Recovery Model' lardan bahsedeceğim. Ne işe yaradıklarından ve hangisini ne gibi durumlarda kullanabileceğinizi anlatacağım.

SQL Server' da üç adet Recovery Model kullanabileceğinizi söylemiştim, bunlar:
- FULL
- BULK LOGGED ve
- SIMPLE' dır.

Peki nedir Recovery Model, ne işe yarar?
Recovery Model, bir veritabanı özelliğidir ve istenildiğinde değiştirilebilir. Yedekleme ve açma (Backup ve Restore) işlemleri Recovery Model bağlamında gerçekleşir. Veritabanınız için belirlediğiniz Recovery Model, veritabanınızın yedeğini alma ve açma seçeneklerinizi belirleyecektir. Bu nedenle özellikle trafiği yoğun olan veritabanlarında çok dikkat etilmesi gereken bir ayardır. Bir veritabanının Recovery Model ayarı, Transaction Log' ların nasıl kaydedileceğini belirler. SQL Server' da, Transaction Log' un tutulmaması diye bir şey yoktur. Her halükârda Transaction Log' a veriler kaydedilir (BULK LOGGED' da bazı istisnalar göreceksiniz), ama bu kayıtların nasıl işleneceğini ve yönetileceğini Recovery Model' larla belirlersiniz.

Not
Yeni oluşturduğunuz bir veritabanı, diğer ayarlar ve nesneler gibi Recovery Model ayarını da Model sistem veritabanından alır.


FULL Recovery Model
Eğer veritabanınız bir üretim (Production)* veritabanıysa, veritabanında bir sorun olduğunda veri kaybına tahammül yoksa ve sıkı bir yedekleme gerekiyorsa veritabanınızın Recovery Model' ının FULL olması gerekmektedir. Böylece, veritabanınız üzerinde gerçekleştirilen her işlem tam olarak kaydedilir ve yedeği alınabilir. Böylece, hata anına kadarki verilerinizi yedekleyebilir ve Hata Anı (Point of Failure) denilen ana kadar verilerinizin yedeğini alabilir ve o ana yedekleriniz ile tekrar ve tam olarak dönebilirsiniz. Bunu en güvenli şekilde FULL Recovery Model ile sağlayabilirsiniz.

* Üretim (Production) ortamı = Bunun anlamı, veritabanınızın çalışan ve dinamik bir sistemde kullanıldığıdır. Meselâ bir fabrikada veya bir hastanedeki veritabanını örnek olarak verebilirim. Bunlar üretim ortamlarıdır. Test ortamı ise farklıdır. Test ortamında veri kaybı genellikle sorun olmaz ama üretim ortamlarında veri kaybı genellikle kabul edilebilir değildir ve bu nedenle işinizden olabilir, hatta ve hatta çok ciddi yaptırımlar ile karşılaşabilirsiniz.

BULK LOGGED Recovery Model
BULK LOGGED Recovery Model' ı toplu (BULK) işlemler yapmak istediğimizde, ama bu toplu işlemlerin Transaction Log dosyamızı büyütmesini istemediğimizde kullanırız.

Peki hangi toplu işlemler BULKED LOGGED Recovery Model kullanıldığında en az şekilde Transaction Log dosyasına kaydedilir? Şunlar:

- bcp, INSERT ... SELECT * FROM OPENROWSET(BULK...), ve BULK INSERT.
- WRITETEXT ve UPDATETEXT ile text, ntext ve image veritiplerine yeni veri oluşturduğunuzda ve eklediğinizde. Dikkat edin, güncelleme işlemi yaptığınızda Transaction Log' unuzda tam kayıt yapılır.
- SELECT INTO
- CREATE INDEX, ALTER INDEX REBUILD veya DBCC DBREINDEX, DROP INDEX
- UPDATE kullanarak büyük değerli veritiplerine yapılan kısmi güncellemeler (varchar(max), text, ntext gibi...)

Bu Recovery Model, FULL Recovery Model ile birlikte kullanılmalıdır. Şöyle ki, FULL Recovery Model' da her işlemin kaydının tutulduğunu ve Hata Anına dönebileceğimizi söylemiştim. BULK LOGGED' da ise toplu (BULK) bir işlem yapıldığında ve o anda veritabanında bir hasar oluştuğunda hata anına geri dönemezsiniz. Bu nedenle normalde, eğer Hata Anına dönebilmeyi istiyorsanız ve verileriniz sizin için çok önemliyse ve sürekli INSERT\UPDATE\DELETE işlemleri yapılıyorsa üretim ortamları için FULL Recovery Model' ı öneriyorum. Ama geçici olarak BULK işlemlerin Transaction Log' a kaydedilmemesi için BULK LOGGED' a geçiş yapıp, sonra toplu işlemleri bitirdikten sonra hemen FULL' e dönüş yapabilirsiniz. Böylece, Transaction Log' unuzun şişmesini engellersiniz ve işlemleri hızlandırırsınız çünkü yapılan her toplu işlem Transaction Log' a kaydedilmemiş olacak; bu da işlemleri hızlandıracak.

SIMPLE Recovery Model
Program geliştiriciler ve veritabanını test edenler için en uygun Recovery Model' dır. Her işlem Transaction Log' a kaydedilir, hangi Recovery Model' ı seçerseniz seçin veritabanına karşı yapılan işlemler kaydedilir demiştim, BULK LOGGED' da da bazı istisnaları gördük.

SIMPLE Recovery Model' da da aynen FULL Recovery Model' da olduğu gibi tüm işlemler Transaction Log' a kaydedilir, fakat her Checkpoint' ten sonra aktif olmayan sanal kayıtlar (Inactive Virtual Logs) Transaction Log dosyası içinden silinirler. Böylece Transaction Log dosyanız sürekli büyümez. Aktif olmayan sanal kayıtlar, temizleme esnasında Transaction Log dosyası içindeki dosyanın en sonunda bulunan aktif sanal kaydına kadar temizlenebilir. Aktif sanal kayıt da, Transaction Log dosyasında o anda hâlâ işlem görüyor olan bir Transaction işlemidir. (Açık işlemler DBCC OPENTRAN komutuyla görüntülenebilir.) Temizleme işlemi dosyanın sonundan başına doğru yapılır, bu nedenle yukarıdaki satırlarda Transaction Log dosyası içindeki en son aktif sanal kayda vurgu yaptım. Aktif sanal kayıtlar, işlem bitene kadar temizlenemezler.

Bu Recovery Model, OLAP olarak kullanılan veritabanları için de uygundur. Bu tür veritabanları sadece raporlama amaçlı kullanıldığından ve üzerlerinde güncelleme yapılmadığından, ki yapılsa bile çok nadir yapıldığından ve genelde de Salt-Okunur (Read Only) olduklarından dolayı Recovery Model' larının SIMPLE olması oldukça olağandır. Çünkü bu tür veritabanları zaten pek yedeklenmezler, çünkü üzerlerinde güncelleme yapılmaz.

Sistem Veritabanları (master, msdb, model, tempdb)
Sistem veritabanlarının varsayılan Recovery Model ayarları aşağıdaki gibidir:

- "master" = SIMPLE : Çünkü bu veritabanını sürekli yedeklemeye gerek yoktur. Sadece SQL Server düzeyinde değişiklikler yaptığınızda (Login, Linked Server gibi...) tam yedekleme yapmanızı öneririm.
- "msdb" = SIMPLE : Bu veritabanı bazı durumlarda çok kullanılıyor olabiliyor, yani istisnalarını gördüm. Ama genel olarak SIMPLE kalmasında bir sakınca yok.
- "model" = FULL : Yazıma başlarken yukarıda da söylemiştim, yeni veritabanlarınız "model" sistem veritabanı model alınarak oluşturulur. Bu nedenle yeni veritabanlarınızın eğer varsayılan olarak FULL Recovery Model' ı kullanılarak oluşturulmasını istiyorsanız, o zaman "model" veritabanının Recovery Model' ını buna göre ayarlayın veya başka isteğinize göre...
- "tempdb" = SIMPLE : Bu veritabanı zaten her SQL Server servisini durdurup başlattığınızda otomatik olarak silinip tekrar oluşturulduğu ve üzerinde sadece geçici işlemler yapıldığı için SIMPLE olması en iyisidir.

Peki bir veritabanının Recovery Model ayarını nasıl değiştirebilirsiniz?
Bu ayar değişikliği için ister SQL Server 2005 ile birlikte gelen (Express Edition hariç) ve SQL Server' ı yönetmek için kullanabileceğimiz arayüz aracı olan SQL Server Management Studio (SQL Server 2005 veya 2000) kullanarak, isterseniz SQL Server 2000 ile birlikte gelen Enterprise Manager arayüzünü kullanarak veritabanınızın özelliklerine (Properties) gidip, seçenekler (Options)' den Recovery Model' ı değiştirebilirsiniz.

Bu ayarı SQL Server 2005' teki Query Editor veya SQL Server 2000' deki Query Analyzer ile de değiştirebilirsiniz. Aşağıdaki örneklere bakın:

Recovery Model' ı FULL yapmak için:
ALTER DATABASE DenemeVT SET RECOVERY FULL

Recovery Model' ı BULK LOGGED yapmak için:
ALTER DATABASE DenemeVT SET BULK_LOGGED FULL

Recovery Model' ı SIMPLE yapmak için:
ALTER DATABASE DenemeVT SET RECOVERY SIMPLE



Ekrem Önsoy

"The statement BACKUP LOG is not allowed while the recovery model is SIMPLE. Use BACKUP DATABASE or change the recovery model using ALTER DATABASE."

HATA MESAJI:
"The statement BACKUP LOG is not allowed while the recovery model is SIMPLE. Use BACKUP DATABASE or change the recovery model using ALTER DATABASE."

AÇIKLAMA:
Recovery Model' ı SIMPLE olan bir veritabanınızın Transaction Log yedeğini almaya çalıştığınızda bu hatayı alırsınız.

ÇÖZÜM:
Recovery Model' ı SIMPLE olan bir veritabanının Transaction Log yedeği alınamaz. Çünkü Recovery Model' ı SIMPLE olan bir veritabanındaki Pasif Sanal Log' lar her Checkpoint' te otomatik olarak silinirler.

Recovery Model' lar konusunda daha fazla bilgi almak için "Recovery Models: FULL, BULK LOGGED, SIMPLE" isimli makalemi okuyabilirsiniz.

7 Ocak 2008 Pazartesi

"The instance name specified is invalid."

HATA MESAJI:
"The instance name specified is invalid."

AÇIKLAMA:
SQL Server MSDE kurmaya çalıştığınızda bu hata mesajı ile karşılaşabilirsiniz.

ÇÖZÜM:
Sorun (şimdiye tecrübe ettiğim tüm örneklerde), kurmaya çalıştığınız SQL Server instance' ının zaten önceden de aynı sistemde kurulu olmasından kaynaklanıyor.

Meselâ bilgisayarınızda herhangi bir SQL Server versiyonu ve sürümünün Default Instance (Varsayılan Örnek)' ı var. Siz de MSDE' yi kurmak için Setup.exe' sinin üstüne çift tıklayıp çalıştırdığınızda veya güçlü bir SA şifresi girerek komut satırından çalıştırmayı denediğinizde (eğer INSTANCENAME seçeneğini kullanmamışsanız) MSDE, SQL Server' ı Default Instance olarak kurmaya çalışacaktır. Bir sistemde sadece bir tane SQL Server Default Instance' ı olabileceği kuralından yola çıkarsak, bu şekilde MSDE' yi kuramayacağınız sonucuna varırız.

"The instance name specified is invalid." hata mesajını aldıktan sonra MSDE' nin Setup' ını aşağıda verdiğim örneği kendi ortamınıza uyarlayarak çalıştırırsanız sorununuzun büyük ihtimalle çözüleceğini umuyorum.

C:\MCDE\Setup.exe INSTANCENAME="TestInstance" SAPWD="gUcLuS@S1fr3M"

5 Ocak 2008 Cumartesi

SQL Server 2008' de 'TRUNCATE_ONLY' ve 'NO_LOG' BACKUP Seçenekleri

Merhaba arkadaşlar,

Bu yeni senede yazdığım ilk makaleme yeni yılınızı kutlamak ile başlamak istiyorum, iyi seneler olsun hepimize =)

Yeni seneyle beraber yeni yazılımlar da çıkıyor ve bildiğiniz üzere SQL Server 2008 bu yeni Sunucu kategorisindeki yazılımlardan birisi.

Yeni yazılımlarla birlikte elbet de yenilikler de geliyor ve zaman zaman bu yeniliklerden de bahsediyorum. İşte bu makalemde de BACKUP komutunda artık TRUNCATE_ONLY ve NO_LOG ' un artık kullanılamayacağından, çünkü BACKUP komutunun artık bu seçenekleri tanımadığından bahsedeceğim.

Bilmeyenler için kısaca değineyim; TRUNCATE_ONLY VE NO_LOG seçeneklerini sadece BACKUP LOG ile kullanabiliriz. Kullanım amacı ise veritabanına ait bir Transaction Log dosyasındaki Pasif Sanal Log (Inactive Virtual Logs)' ları temizlemek ve Transaction Log içerisine kaydedilecek yeni kayıtlar için yer açmaktır. Bu çok ayrı bir konu, buna başka bir makalede değineceğim.

Bu BACKUP seçeneklerinin, SQL Server' ın gelecekteki versiyonlarında artık kullanılamayacağı zaten SQL Server 2005 Books Online' da belirtilmişti.

Peki SQL Server 2008' de veritabanımızın Transaction Log dosyasındaki Pasif Sanal Log' ları nasıl temizleyeceğiz? Hemen cevabı da geliyor: Veritabanımızın Recovery State' ini SIMPLE yaparak. Tabii eğer veritabanınızın Recovery State' i zaten SIMPLE ise zaten Transaction Log' unuz otomatik olarak pasif loglardan temizlenecektir. Ama eğer FULL veya BULK LOGGED ise, o zaman veritabanınızın Recovery State' ini SIMPLE yaptıktan sonra tekrar eski haline döndürebilirsiniz.

Örnek:
ALTER DATABASE DenemeVT SET RECOVERY SIMPLE
ALTER DATABASE DenemeVT SET RECOVERY FULL

ÇOK ÖNEMLİ:
Veritabanınızın Recovery State' ini SIMPLE yapmanızın size olan maliyetlerini önceden bilmelisiniz. Aksi takdirde hiç istemediğiniz sonuçlarla karşılaşabilirsiniz. Maksadım kimsenin gözünü kormutmak değil elbet, fakat bu iş bu şekilde yapılıyor diye her şey yolunda gidecek gibi bir durum söz konusu değil. Veritabanınızın Recovery State' ini değiştirmek, Transaction Log zincirini kırar. Yani eğer bahsi geçen veritabanında Transaction Log yedekleme işlemi yapıyorsanız, bu zincir kırılacaktır ve veritabanınızın Recovery State' ini SIMPLE yaptıktan sonraki alınan Transaction Log' lar bir RESTORE durumunda işe yaramayacaktır çünkü zincir kırılmıştır. Bunu engellemek için ise veritabanınızın Recovery State' ini değiştirmeden önce tam yedeğini almanızı ve SIMPLE' dan tekrar FULL' e geçtikten sonra tekrar tam yedeğini almanızı tavsiye ederim.


Ekrem Önsoy

3 Ocak 2008 Perşembe

"A connection was successfully established with the server, but then an error occurred during the login process. (provider: Shared Memory Provider, er

HATA MESAJI:
"A connection was successfully established with the server, but then an error occurred during the login process. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.) (Microsoft SQL Server, Error: 233)"

AÇIKLAMA:
SQL Authentication modunda bir SQL Login ile SQL Server' ınıza giriş yapmaya çalıştığınızda bu hata ile karşılaşabilirsiniz.

ÇÖZÜM:
Ben bu hata ile iki kere karşılaştım şimdiye kadar ve ikisinde de ilgili kullanılar doğru sandıkları bir şifre ile ve SQL Login kullanarak SQL Server' a bağlanmaya çalışıyorlardı.

Misal olarak, kullanıcının bilgileri aslında aşağıdaki gibi:
Kullanıcı adı= sa
Kullanıcı şifresi = xxx

Ama kullanıcı aşağıdaki bilgilerle giriş yapmaya çalışıyor:
Kullanıcı adı= sa
Kullanıcı şifresi = xyx

Şifresinin doğru olduğundan emin, ama aslında değil. Yani demeye çalıştığım şu, eğer bu hata ile karşılaşıyorsanız şifrenizin doğru olduğundan emin olun.

Bu hata ile ilgili daha ayrıntılı bilgiye ilgili SQL Error Log' undan ulaşabilirsiniz. SQL Server' da doğrudan kullanıcıya verilen ve güvenlikle ilgili olan hata mesajlarının üzerleri güvenlik nedeniyle kapalıdır. Güvenlik konusunda SQL Server' ın verdiği hata mesajlarını daha iyi anlayabilmek için SQL Error Log' una bakmakta çok fayda vardır.

Meselâ yukarıdaki hatanın bahsettiğim iki gördüğüm örnekte de SQL Error Log' daki karşılığı şuydu:

"Login failed for user '...'. (Microsoft SQL Server, Error: 18456)

Bu da, '...' kullanıcısı için girilen şifre yanlış demektir.

Not:
Bu durumda hata mesajını mesaja göre değil, hata numarasna göre yorumluyorum. Başka durumlarda ve hata mesajı numaralarında hatanın sebebi daha farklı olabilir.

Ayrıca, bu hatayı bir hesabın durumunun (Status) kullanılamaz (Disabled) olması durumunda da alabilirsiniz.

SQL Server' da varsayılan olarak "sa" hesabının durumu kullanılamazdır (Disabled). Hesabınızı kullanılabilir (Enabled) yaptığınızda da bu sorunu çözebilirsiniz. Bunun için SSMS' i açın ve Security\Logins düğümüne gidin. Orada ilgili kullanıcıyı seçip özelliklerine gidin ve "Status" seçeneğini uygun şekilde ayarlayın.