SQL Server’da MARS (Multiple Active Result Sets) Nedir

MSSQL Server

Microsoft SQL Server mimarisinde verimliliği artıran ancak zaman zaman yanlış anlaşılan kavramlardan biri MARS (Multiple Active Result Sets) özelliğidir. Bu makalede MARS’ın ne olduğunu, ne zaman gerektiğini, SSMS üzerinde nasıl yapılandırılacağını ve DMV (sys.dm_exec_connections) üzerinden mimarisinin nasıl doğrulanacağını adım adım inceleyeceğiz.

Klasik SQL Server bağlantı mimarisinde, tek bir TCP/IP oturumu üzerinden aynı anda yalnızca tek bir aktif işlem veya sorgu sonucu (result set) akar. İstemci (client) tarafında bir SqlDataReader ile veriler okunurken, o okuma işlemi tamamlanmadan aynı bağlantı üzerinden ikinci bir sorgu veya UPDATE komutu gönderildiğinde veri tabanı sürücüsü hata fırlatır.

MARS; tek bir fiziksel bağlantı (Connection) üzerinden aynı anda birden fazla aktif sonuç kümesinin açılmasına ve yönetilmesine imkan tanıyan bir .NET / SQL Server özelliğidir.

Connection string tanımındaki karşılığı şudur:

MultipleActiveResultSets=True;

Mars temel olarak connection string’e yazılabildiği gibi kullanıcı SSMS üzerinden bağlantı gerçekleştirdiğinde bu yapıya geçebilmektedir.

SSMS varsayılan olarak sonuçları sırayla işlediği için uygulamalardaki gibi belirgin bir mimari fark yaratmaz. C# / .NET / Uygulama Kodu Mars yapısının en çok kullanıldığı yerdir. Bu yapılarda kullanıldığında belirğin olarak görülebilir. Yine de SSMS üzerinden bu yapının nasıl oluşturulduğunu görelim.

SSMS Connect to Server penceresinden Options >> butonuna tıklayarak Additional Connection Parameters sekmesine geçilir.

Additional Connection Parameters bölümüne MultipleActiveResultSets=True parametresi girilir.

MARS’ın arka planda nasıl çalıştığını görmenin en net yolu sys.dm_exec_connections DMV’sini sorgulamaktır.

Normal (Standart) Bağlantılar: Fiziksel veya işletim sistemi düzeyindeki protokolleri gösterir.

  • TCP (Ağ üzerinden IP ile bağlantı)
  • Shared Memory (Sunucunun kendi içindeki yerel bağlantı)
  • Named Pipes (Etki alanı / domain içi borulama)

MARS Bağlantıları: Session değerini alır.

MARS ile açtığınız sorgu penceresinde aşağıdaki T-SQL kodunu çalıştırın:

SELECT 
    s.session_id,
    s.login_name,
    s.host_name,
    s.program_name,
    c.net_transport,
    c.num_reads,
    c.num_writes,
    CASE 
        WHEN c.net_transport = 'Session' THEN 'Evet (MARS Aktif Alt Oturum)'
        ELSE 'Standart Bağlantı (veya MARS Ana Bağlantısı)'
    END AS MARS_Durumu
FROM sys.dm_exec_sessions s
JOIN sys.dm_exec_connections c ON s.session_id = c.session_id
WHERE s.session_id = @@SPID;

Sorguyu çalıştırdığınızda aynı session_id için birden fazla satır dönecektir:

  • Shared Memory / TCP: Fiziksel bağlantı hattını temsil eder.
  • Session: MARS’ın aynı fiziksel hat üzerinde oluşturduğu mantıksal alt oturumlardır (multiplexed sessions). net_transport alanında Session ifadesini görmek, o oturumun aktif olarak MARS mimarisini kullandığının kesin kanıtıdır.

MARS kullanırken en sık karşılaşılan hatalardan biri açık kalan transaction yönetimidir.

BEGIN TRAN

SELECT * FROM [dbo].[Table_1];

INSERT INTO [dbo].[Table_1](isim, soyad) VALUES ('abdullah', 'yücel');

UPDATE [dbo].[Table_1] SET soyad='yüce' WHERE id=3;

DELETE FROM [dbo].[Table_1];

Eğer blok sonunda COMMIT TRAN veya ROLLBACK TRAN ile işlem sonlandırılmazsa, SQL Server MARS kuralları gereği şu hatayı döndürür:

Msg 3997, Level 16, State 1:

A transaction that was started in a MARS batch is still active at the end of the batch. The transaction is rolled back.

Nedeni: MARS açıkken bir sorgu bloğu (batch) tamamlandığında açık kalmış bir işlem paketine izin verilmez. SQL Server veri bütünlüğünü korumak adına yapılan tüm işlemleri otomatik olarak geri alır (ROLLBACK). Çözüm için blok sonuna mutlaka commit komutunun eklenmesi gerekir.

Avantajları ve Dezavantajı

  • Avantaj: Ekstra connection açma maliyetini düşürür, kilitlenmeleri (deadlock) azaltabilir ve iç içe okuma/yazma işlemlerini kolaylaştırır.
  • Dezavantajı: MARS altında çalışan ve veriyi okurken eş zamanlı veri değiştiren (SELECT okuması yaparken UPDATE/INSERT çalıştırmak gibi) sorgular, veri tutarlılığını sağlamak için Row Versioning mekanizmasını tetikler. Bu veriler tempdb üzerinde saklandığından tempdb i/o yükü ve doluluğu artar.
  • MARS, aktif her sonuç kümesi için sunucu belleğinde (buffer) ek alan ayırır ve bağlantı başına ortam durumunu (environment state) takip eder. Bu durum CPU ve bellek kullanımını artırır.
  • Aynı bağlantı/oturum içinde çalışan iki işlem birbirini bloklayabilir veya deadlock’a neden olabilir. Bir işlem tablodan okuma yaparken (Shared Lock) diğer işlem aynı tabloya yazmaya çalışırsa (Exclusive Lock) bekleme süreleri (Wait Types) ve kilit çakışmaları artar.
  • MARS, tek bir bağlantı üzerinde aynı anda yalnızca tek bir aktif işlem (Transaction) yürütülmesine izin verir. Bağlantıda BEGIN TRANSACTION başlatıldığında, bu bağlantıdan gönderilen diğer tüm komutlar da aynı transaction kapsamına girer. Bir sonuç kümesi açıkken yapılan bir hata veya ROLLBACK, açık olan diğer sonuç kümelerinin de beklenmedik şekilde patlamasına/kapanmasına yol açabilir.
  • MARS açık olduğunda geliştiriciler genellikle “bağlantı açıp kapatma” maliyetinden kaçınmak için tek bir bağlantıyı sürekli açık tutma eğilimine girer. Bağlantı havuzunun (Connection Pool) etkin kullanılmasını engeller. Uzun süreli açık kalan bağlantılar (Long-running connections) sunucu üzerinde gereksiz oturum birikmesine ve kaynak kilitlenmelerine neden olur.

MARS işlemleri paralel izole işlemler değildir, sadece aynı bağlantı hattını sırayla/bölüşerek kullanırlar. Büyük veri yüklerinde performans için MARS yerine veriyi tek seferde belleğe çekip (ToList()) ardından güncellemek veya JOIN / UPDATE SQL sorguları yazmak daha performanslıdır.

Aşağıdaki connection string yapısında MARS yapısının açık olduğu görülmektedir.

// Connection String'de MARS açık:
string connString = "Server=localhost;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=True;";

Sonuç olarak MARS doğru senaryoda kod karmaşasını çözen esnek bir mimari sunsa da, getirdiği TempDB yükü ve kilitlenme riskleri nedeniyle kontrolsüz kullanıldığında bir performans darboğazına dönüşebilir; bu nedenle yalnızca ihtiyaç anında ve bilinçli bir kaynak yönetimiyle uygulanmalıdır.

Not: Uygulama sunucularında connection string ilgili dizinde bulunmaktadır. C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config

Başka makalede görüşmek dileğiyle..

“İlminle övünme, Şeytan’a bak!” Araf-12

Author: Yunus YÜCEL

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir