Sepetiniz

Delayed Durability Nedir

Delayed Durability SQL Server 2014 ile gelen bir özelliktir. Gelişmiş ilişkisel veritabanlarının ortak özelliği olan Durability’yi esneten bir özelliktir. “SQL Server ACID Kuralları” isimli makaleyi okumak isteyebilirsiniz.

 

SQL Server Default olarak şu şekilde çalışır:

 

Veri ldf dosyasına yazılmadan(log flush) data dosyalarına yazılma işlemi(page flushing) gerçekleşmez. Bu mekanizma SQL Server WAL(Write Ahead Log) olarak karşımıza çıkar. “Database Checkpoint Nedir” isimli makalede detayları bulabilirsiniz.

 

Bu doğrultuda veri ldf dosyasına yazılmadan kullanıcıya işleminiz tamamlandı bilgisi de iletilmez. Böylelikle herhangi bir crash anında, sql server veriyi log dosyasından recover edebilir. Bu şekilde verinizin kaybolmayacağı garanti altına alınmış olur.

 

 

Delayed Durability ile veritabanı seviyesinde, commit işlemi seviyesinde ve atomic block seviyesinde bu işlemi esnetebiliyoruz. Yani log dosyasına yazılmadan kullanıcıya işleminin tamamlandığı bilgisi iletiliyor.

 

NOT : Eğer veritabanı, transaction ya da atomic block seviyesinde transaction’larınızı aşağıdaki şekillerde delayed durable hale getirirseniz performansınız artmasıyla beraber veri kaybı riskiniz ortaya çıkar. Örneğin bir crash anında veriler log dosyasına yazılmadan kullanıcıyla succesful bilgisi iletildi diyelim. Veritabanı açılırken log dosyasından recovery olurken bu bilgi log dosyasında olmadığı için kullanıcıya succesful bilgisi iletilmesine rağmen aslında veritabanında ilgili kayıt olmayacaktır. Bu kısmı anlamadıysanız sizi yine “Database Checkpoint Nedir” isimli makaleye yönlendireceğim.

 

Aşağıdaki script yardımıyla veritabanı seviyesinde delayed durability seçeneklerini set edebiliyoruz.

ALTER DATABASE VeritabaniAdiniz SET DELAYED_DURABILITY = { DISABLED | ALLOWED | FORCED } 

 

Gördüğünüz gibi DISABLED, ALLOWED ve FORCED seçenekleri mevcut.

 

DISABLED, default davranış şeklidir. Yani Delayed Durability’yi veritabanı seviyesinde set ettiyseniz aşağıdaki script yardımıyla tekrar default davranış şekline döndürebilirsiniz.

 

ALTER DATABASE VeritabaniAdiniz SET DELAYED_DURABILITY=DISABLED

 

ALLOWED, durability’nin belirtilen veritabanı içersindeki transaction’larda belirlenmesine izin verildiği anlamına gelir.

 

Transaction seviyesinde aşağıdaki gibi transaction’ı delayed durable hale getirebilirsiniz.

BEGIN TRANSACTION
SELECT 1;
COMMIT TRANSACTION WITH (DELAYED_DURABILITY = ON)

 

In Memory OLTP’deki Natively Compiled Stored Procedure’lerde atomic block seviyesinde aşağıdaki gibi delayed durable hale getirebilirsiniz. Natively Compiled Stored Procedure hakkında detaylı bilgi almak için “Natively Compiled Stored Procedure Nedir ve Nasıl Kullanılır?” isimli makaleyi okumanızı öneririm.

USE [Test]
GO
CREATE PROCEDURE NativelyCompiledSPOrnek
WITH NATIVE_COMPILATION, EXECUTE AS OWNER, SCHEMABINDING
AS BEGIN ATOMIC WITH   
(  
    DELAYED_DURABILITY = ON,  
    TRANSACTION ISOLATION LEVEL = SNAPSHOT,  
    LANGUAGE = N'English'  
    …  
)  
END 

--EXEC NativelyCompiledSPOrnek

 

FORCED, veritabanı içersindeki tüm transaction’ların delayed durable şekline çalışmasına zorlanmış demektir.

 

ALTER DATABASE VeritabaniAdiniz SET DELAYED_DURABILITY=FORCED

 

SQL Server ACID Kuralları

ACID, ilişkisel veritabanı yönetim sistemlerinin(RDBMS) sağlaması gereken 4 ana kuraldır. İlişkisel veritabanları ve sql server hakkında daha detaylı bilgi almak için “SQL Server Nedir?” isimli makaleyi okumak isteyebilirsiniz.

ACID Kuralları:

 

Atomicity (Bölünmezlik): Ya hep Ya Hiç prensibini benimser. Bir transaction içersinde bir işlem fail ediyorsa tüm işlemler her durumda(sunucu kapanması , hata alınması) fail etmelidir.

 

Consistency (Tutarlılık): Transaction bitimine kadar, eğer  constraintscascadestriggers gibi tanımlanmış kuralların ihlali gerçekleşirse veritabanındaki bütün veri transaction başlamadan önceki hali ile kalmalıdır.

 

Isolation (İzolasyon): Aynı anda aynı veri üzerinde birden fazla transaction değişiklik yapamamalıdır. Bir transaction bir alanda işlem yapıyorsa işlemi bitene kadar bu alan diğer transaction’lardan izole edilmelidir. SQL Server’da bir çok Isolation Level vardır. Default olarak Read Committed Isolation Level’i kullanır. Isolation Level’ler ile ilgili aşağıdaki makaleleri okuyabilirsiniz.

Isolation Level 1“,

Isolation Level 2“,

Isolation Level 3

 

Durability (Süreklilik): Eğer bir transaction başarılı bir şekilde gerçekleştiyse(commit edildiyse) bu veri sistem fail etse bile garanti altında olmalıdır. Örneğin bir update işlemini commit ettiniz tam o esnada sunucu kapandı. SQL Server Transaction Log dosyası yardımıyla bu özelliği sağlar. “SQL Server Transaction Log Nedir” isimli makaleyi okumak isteyebilirsiniz.

In Memory OLTP Nedir? Ve Nasıl Kullanılır?

In Memory OLTP SQL Server 2014 ile birlikte gelen bir özelliktir. Bu özellik ile verilerimizi artık memory’de tutabiliyoruz. Verileri memory’de tutabiliyoruz dediğimizde, sql server’a ilgisi olan bir çok insan buffer pool olarak algılıyor. Önemli bir nokta olarak veriler buffer pool’da değil, direk memory’de tutuluyor. “Buffer Pool Extension Nedir” isimli makalemde buffer pool’un ne olduğuna değinmiştim.

 

Tabi tüm verimizi memory’de tutmamız çoğunlukla olası değildir. Çok yoğun transaction alan tablolar için ya da çok hızlı cevap almak istediğimzi tablolar için bu özelliği kullanabiliriz. Tabi SQL Server 2014’te çok hoşunuza gitmeyecek bir takım kısıtlamaları var. Bu makalede SQL Server 2014 ile gelen bu özelliğin SQL Server 2016 ile nasıl geliştiğini adım adım inceleyeceğiz.

 

Öncelikle SQL Server 2014 ile bu özelliği size tanıtıp sonrasında SQL Server 2016 ile gelen yeniliklerine değineceğim. In Memory OLTP ile ilgili karşımıza gelen ilk özellik memory’de tutulan tablolar olarak bilinen memory optimized table’lardır.

 

SQL Server 2014 için Memory Optimized Table:

 

İlk olarak memory optimized tabloyu oluşturalım ve daha sonra açıklamalara geçelim. Tabloyu oluşturmak için öncelikle aşağıdaki script yardımıyla memory optimized filegroup’u oluşturmamız gerekiyor. Daha sonra bu filegroup içersinde bir file oluşturuyoruz.

ALTER DATABASE [Test]
ADD FILEGROUP [InMemoryFileGroup] CONTAINS MEMORY_OPTIMIZED_DATA
GO
ALTER DATABASE[Test]
ADD FILE(
NAME=N'InMemoryFile1',
FILENAME=N'C:\MSSQL\InMem'
) TO FILEGROUP [InMemoryFileGroup]

 

Daha sonra aşağıdaki gibi tablomuzu oluşturalım.

CREATE TABLE  dbo.MemTabloOrnek
(
ID int NOT NULL
PRIMARY KEY NONCLUSTERED HASH (ID)  WITH  (BUCKET_COUNT =1024),
AdSoyad varchar(250) NOT NULL
INDEX IDX_AdSoyad  HASH (AdSoyad) WITH  (BUCKET_COUNT =1024)
) WITH (MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_AND_DATA)

 

Tablomuzu oluşturmak istediğimizde aşağıdaki gibi bir hata alabilirsiniz.

 

Msg 12329, Level 16, State 103, Line 1

The data types char(n) and varchar(n) using a collation that has a code page other than 1252 are not supported with memory optimized tables.

 

Bu hata memory optimzed tablo’ların bütün collation tiplerini desteklememesinden kaynaklanmaktadır.

 

Aşağıdaki script yardımıyla desteklediği collation tiplerini görebilirsiniz.

 

SELECT NAME ,COLLATIONPROPERTY(NAME, 'codepage') AS [CodePage] FROM sys.fn_helpcollations()
WHERE COLLATIONPROPERTY(NAME, 'codepage') = 1252

 

Tablomuzu oluşturabilmek için veritabanımızın collation’ını aşağıdaki script yardımıyla değiştirebilirsiniz.

 

USE master
GO
ALTER DATABASE Test COLLATE SQL_Latin1_General_CP1_CI_AS

 

Ya da veritabanı collation’ını değiştirmeden aşağıdaki script yardımıyla da tablonuzu oluşturabilirsiniz.

CREATE TABLE  dbo.MemTabloOrnek
(
ID int NOT NULL
PRIMARY KEY NONCLUSTERED HASH (ID)  WITH  (BUCKET_COUNT =1024),
AdSoyad varchar(250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
INDEX IDX_AdSoyad  HASH (AdSoyad) WITH  (BUCKET_COUNT =1024)
) WITH (MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_AND_DATA)

 

Oops. Yine hata aldık. Bu hataları almadan direk çalışan script’i de sizinle paylaşabilirdim fakat bu hataları da görmenizi istedim. Şimdi aldığımız hata aşağıdaki gibi.

 

Msg 12328, Level 16, State 102, Line 1

Indexes on character columns that do not use a *_BIN2 collation are not supported with indexes on memory optimized tables.

Msg 1750, Level 16, State 0, Line 1

Could not create constraint or index. See previous errors.

 

Varchar bir kolona index koymak için collation’ın BIN2 olması gerekiyor. Aşağıdaki sorgu yardımıyla BIN2 tipinde olan collation’ları listeleyip size uygun olanı seçebilirsiniz.

 

SELECT NAME,COLLATIONPROPERTY(NAME, 'codepage') AS [CodePage] FROM sys.fn_helpcollations()
WHERE COLLATIONPROPERTY(NAME, 'codepage') = 1252 and NAME like '%BIN2%'

 

Ben Latin1_General_BIN2 collation’ını kullanarak tabloyu aşağıdaki gibi yeniden oluşturuyorum.

 

CREATE TABLE  dbo.MemTabloOrnek
(
ID int NOT NULL
PRIMARY KEY NONCLUSTERED HASH (ID)  WITH  (BUCKET_COUNT =1024),
AdSoyad varchar(250) COLLATE Latin1_General_BIN2 NOT NULL
INDEX IDX_AdSoyad  HASH (AdSoyad) WITH  (BUCKET_COUNT =1024)
) WITH (MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_AND_DATA)

 

Bu sefer hata almadan tablomuzu oluşturabildik.

 

Script’i biraz inceleyecek olursak bize yabancı gelebilecek birkaç farklılık var.

 

MEMORY_OPTIMIZED = ON: Tablonun memory optimized tablo olduğunu belirtiyor.

 

HASH INDEX: Memory Optimized tablolar normal btree index’i desteklemez. Her memory optimized tabloda en az bir tane index olmak zorundadır. Bu index bütün satırları tabloda birleştirme işlevini görür.

 

BUCKET_COUNT: hash index oluşturulurken, bu kolondaki unique satır sayısını belirtir. Doğru bir sayı belirlemezseniz performans azalır ve veritabanının recovery süresi uzar. Eğer bucket_count’u belirleyemiyorsanız bunun yerine range index kullanabilirsiniz. Eğer index’i hash olarak belirtmezseniz bu index range index olacaktır.

 

DURABILITY: SCHEMA_AND_DATA ya da SCHEMA_ONLY olabilir.

 

SCHEMA_AND_DATA olursa hem şema yapısı hem de veri beklenmedik bir crash durumunda ya da always on failover durumunda korunur.

 

SCHEMA_ONLY olursa sadece şema yapısı beklenmedik bir crash durumunda ya da always on failover durumunda korunur. Dolayısıyla verinizi kaybedersiniz.

 

Biraz mantıksal yapısından bahsedelim.

 

In Memory OLTP’nin en önemli özelli lock ve latch olmadığı için performansı çok ciddi anlamda arttırmasıdır. Microsoft 5-30 kata kadar performans artışı olduğunu belirtiyor.

 

Bildiğimiz normal tablolar Disk Based Table olarak geçer. Disk Based tablolar’a bir select sorgusu geldiğinde veriler diskten cache’e aktarılır. Memory Optimized Table’lar zaten memory’de tutuldukları için böyle bir işleme gerek kalmaz.

 

Sadece sunucuda bir crash olması durumunda memory’de tutulan verilerin kaybolmaması ve veritabanının sağlıklı bir şekilde recover olması için bazı checkpoint dosyaları(data ve delta dosyaları) yukarda bahsettiğim memory optimized filegroup üzerinde tutulur.

 

Memory Optimized Tablolar’da Disk Based Tablolar ile aynı transaction log dosyasını kullanır. Bildiğiniz gibi bu dosya diskt’te tutulur. “SQL Server Transaction Log Nedir” isimli makalemi okumak isteyebilirsiniz.

 

Index’ler her zaman memory’de tutulur. Restart sonrasında otomatik olarak rebuild edilirler. Buda recovery süresini biraz uzatır. Bu yüzden index koyarken dikkatli olmanız gerekir.

 

In Memory OLTP’de ki en iyi performansı natively compiled stored procedure’leri memory optimized tablolar ile birlikte kullanarak elde edebilirsiniz. “Natively Compiled Stored Procedure Nedir ve Nasıl Kullanılır?” isimli makalemi okumak isteyebilirsiniz.

 

Memory Optimized tablolara erişim normal tablolara erişim ile aynıdır. Aynı uygulama aynı veritabanı içersinde hem memory optimized tabloları hem de disk based tabloları kullanabilir.

 

Memory Optimized tablolar optimistic concurrency control kullanır.”Optimistic ve Pessimistic Concurrency Control Nedir” isimli makalemi okumak isteyebilirsiniz.

 

Memory Optimized Tabloların bazı kısıtlamaları vardır: Daha detaylı kısıtlamaları makalenin devamındaki tabloda bulabilirsiniz.

 

  • DML Trigger
  • XML ve CLR veri tipleri.
  • Varchar(max) gibi LOB tipleri.
  • FOREIGN KEY
  • CHECK Constraint
  • ALTER TABLE
  • Sonradan Index oluşturma ve kaldırma(tabloyu yeniden oluşturmamız gerekir.)
  • TRUNCATE TABLE
  • 8 index’ten fazlasını desteklemez

 

 

SQL Server 2016 ile in memory OLTP’de nasıl yenilikler geldi?

 

SQL Server 2014 ve SQL Server 2016’da In Memory Oltp farklarını aşağıdaki tabloda görebilirsiniz.

 

Özellik ve Limitler

SQL Server 2014

SQL Server 2016

Maksimum Tablo Büyüklüğü

256 GB

Limit yok

Transparent Data Encryption (TDE)

Desteklemiyor

Destekliyor

İç içe(Nested) Natively Compiled Procedure

Desteklemiyor

Destekliyor

Natively-compiled scalar UDF(user defined function)

Desteklemiyor

Destekliyor

ALTER TABLE,PROCEDURE,INDEX

Desteklemiyor

Destekliyor(OFFLINE)

AFTER TRIGGER

Desteklemiyor

Destekliyor(WITH NATIVE_COMPILATION ile)

Nullable kolonlar’da index

Desteklemiyor

Destekliyor

BIN2 olmayan kolonlarda index

Desteklemiyor

Destekliyor

Foreign Keys

Desteklemiyor

Destekliyor

Check/Unique Constraints

Desteklemiyor

Destekliyor

Parallelism

Desteklemiyor

Destekliyor

OUTER JOIN, OR, NOT, UNION [ALL], DISTINCT, EXISTS, IN

Desteklemiyor

Destekliyor

Multiple Active Result Sets (MARS)

Desteklemiyor

Destekliyor

SSMS Üzerinde Tablo Design İşlemleri

Desteklemiyor

Destekliyor

Memory Optimized Tablolarda ColumnStore Index

Desteklemiyor

Destekliyor

Varbinary(max),varchar(max),nvarchar(max)

Desteklemiyor

Destekliyor

Natively Compiled SP’de EXECUTE AS OWNER ifadesi

Gerek var

Gerek Yok

 

Index rebuild ederek BUCKET_COUNT’u aşağıdaki şekilde değiştirebiliyorsunuz.

 

ALTER TABLE dbo.MemTabloOrnek
  ALTER INDEX IDX_ID
  REBUILD WITH (BUCKET_COUNT = 1042);

 

SQL Server 2017’de de In Memory OLTP’ye aşağıdaki yenilikler geldi.

 

  • Sp_spaceused memory optimized tablolar için artık kullanılabiliyor.
  • Sp_rename memory optimized tablolar ve natively compiled module’ler için artık kullanılabiliyor.
  • Natively compiled module’ler için CASE desteği geldi.
  • Memory optimized tablolarda 8 index limiti vardı. Bu limit kaldırıldı.
  • TOP (N) WITH TIES artık Natively compiled module’lerde destekleniyor.
  • Memory optimized tablolarda ALTER TABLE işlemi hızlandı.
  • Transaction Log redo işlemi paralel yapılıyor. Bu da recovery süresini kısalttı.
  • Memory optimized filegroup’lar Azure Blob Storage’de saklanabiliyor.
  • Memory optimized tablolar için, üzerinde index oluşturulabilir computed column desteği geldi.
  • Natively compiled module’lerde ve CHECK Constraint’in için JSON fonksiyonları kullanılabiliyor.
  • Natively compiled module’lerde CROSS APPLY operatörü kullanılabiliyor.
  • Memory Optimized Tablolardaki nonclustered index’lerin rebuild işlemi optimize edildi. Bu iyileştirme ile nonclustered index kullanan memory optimized tabloların olduğu veritabanları için recovery süresi kısaldı.